Evaluate the scoring component, SVG half-star solution!

前端小智
中文
Author: KUMAR HARSH
Translator: Frontend Xiaozhi
Source: blog

If you have dreams and dry goods, search for [Great Migration to the World] attention to this brushing wit who is still doing dishes in the early morning.

This article GitHub https://github.com/qq449245884/xiaozhi has been included, the first-line interview complete test site, information and my series of articles.

Evaluation and scoring is also an important part of a content service website. It helps to analyze the user's preference for our content. Recently, our group needs to implement a star-rated evaluation component for a project. The requirements are as follows:

  • Performance (cannot use pictures)
  • Adjustable size
  • Accessibility
  • Score with decimal places (such as: 3.5 or 3.2 )
  • Use css to directly control the style

To meet the above requirements, frequent investigations, and finally chose the SVG solution.

Task

The following picture is the final effect we want:

image.png

Our main job is to let the star change its color, stroke, size, and display half of the star.

accomplish

Before implementation, we need to have a basic SVG structure as follows:

<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
    <path d="..."/>
</svg>

Add aria-label

Add aria-label allow users to access this information using a screen reader.

<p aria-label="Rating is 4.5 out of 5">
   <svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
      <path d="..."/>
   </svg>
</p>
The aria-label attribute is used to describe the label added to the current element and accepts a string as a parameter. It is to label the element in an invisible way (if the described element has a real description element, you can use the aria-labelledby attribute to bind the description element and the described element instead).

How to reuse SVG

We can copy the above SVG tag five times, or extract the path data and save it somewhere, and then reuse it without repeating the code. We choose the latter.

First, we need to create an SVG with zero width and height so that it does not reserve space.

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Content -->
</svg>

In this SVG, we need to include path data <symbol> According to MDN:

The symbol element is used to define the graphic template object, which can be instantiated <use>

<symbol> is the same as the content of the icon. In addition, id , so that we can refer to this symbol .

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
    <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" id="star">
        <path d="..."/>
    </symbol>
</svg>

With this setting, we can now reuse the symbol <use> element. The approach is to use id as the value of the href

<p class="c-rate">
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
</p>

Star pattern

With the star structure above, let's add styles now:

<p class="c-rate">
    <svg class="c-icon active" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon active" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon active" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon active" width="32" height="32">
      <use href="#star"></use>
    </svg>
    <svg class="c-icon" width="32" height="32">
      <use href="#star"></use>
    </svg>
</p>
.c-icon {
    --star-active: #fece3c;
    --star-inactive: #6c6962;
    fill: var(--star-inactive);
}

.c-icon.active {
    fill: var(--star-active);
}

The result after running:

image.png

Half star

It is easy to make half a star after using SVG, and there are two good solutions. The first is to use <masks> , and the second is to use SVG gradients.

Use <masks>

The purpose of using masks is to simulate the effect of erasing a part of the star and painting the other part in a translucent color.

image.png

In the picture above, there is a square and a star. Their intersection is the result we want.

The approach is as follows:

  • Create a reusable SVG template
  • Add a <mask> element, the position is x=50%
  • Apply mask to the stars
<!-- The reusable SVG template -->
<svg viewBox="0 0 32 32" id="star">
  <defs>
    <mask id="half">
      <rect x="50%" y="0" width="32" height="32" fill="white" />
    </mask>
    <symbol viewBox="0 0 32 32" id="star">
      <path d="..." />
    </symbol>
  </defs>
</svg>

<svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
    <use href="#star" mask="url(#half)" fill="green"></use>
</svg>

The question is, when a translucent star is obscured, how can we show it? Well, thanks to SVG, we can include multiple elements <mask>

<mask id="half">
  <rect x="0" y="0" width="32" height="32" fill="white" />
  <rect x="50%" y="0" width="32" height="32" fill="black" />
</mask>

In mask , the white elements represent the content we want to display, and the black elements represent the content we want to hide. When combined together, we can create a cut-out effect effect.

image.png

Note that the white rectangle is positioned at 0,0 , and the black rectangle is positioned at 50%,0 . Here are its effects:

image.png

The scribbled part represents the final result, half a star. Now, you may be thinking, how to add another semi-transparent star to make it clearer?

By using a lighter color than pure black, we will get a translucent effect. This means that the currently hidden area will have a light star color.

<mask id="half">
  <rect x="0" y="0" width="32" height="32" fill="white" />
  <rect x="50%" y="0" width="32" height="32" fill="grey" />
</mask>

image.png

At this point, we review the complete SVG tag.

<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
   <defs>
      <mask id="half">
         <rect x="0" y="0" width="32" height="32" fill="white" />
         <rect x="50%" y="0" width="32" height="32" fill="grey" />
      </mask>

      <symbol viewBox="0 0 32 32" id="star">
         <path d="..." />
      </symbol>
   </defs>
</svg>

<p class="c-rate">
   <svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
      <use href="#star" mask="url(#half)" fill="green"></use>
   </svg>
   <!-- 4 more stars -->
</p>

In this way, we have a partially filled star. The beauty of this solution is that we don't need to provide two shades, mask will work:

image.png

address: 1614e6d94b2796 https://codepen.io/shadeed/pen/bGWyoXW

This is the end of the first method, let’s look at the second method.

Half star with SVG gradient

Similar to mask , we need to define a gradient in the <defs> element.

<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
    <defs>
        <linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
            <stop offset="50%" stop-color="#f7efc5"></stop>
            <stop offset="50%" stop-color="#fed94b"></stop>
        </linearGradient>
    </defs>
</svg>

Note that we have two color blocks, the first represents the first half, and the second represents the light shade. In this solution, we need to provide two colors manually.

image.png

<p class="c-rate">
    <svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
        <use href="#star" fill="url(#half)"></use>
    </svg>
</p>

address: 1614e6d94b287d https://codepen.io/shadeed/pen/eYWaero

Outline style

Next, let's make an outline for the star so that it looks more three-dimensional.

image.png

SVG Mask solves the problem of contour style

To add a stroke, we only need to add stroke to the SVG element. This will work well for all stars. However, for the part, it will be cut off because of the mask. This is great for complete stars. However, for half a mask , it will be covered due to 0614e6d94b28fc.

image.png

To solve this problem, we need another star profile. This can be achieved by copying the <use> element and deleting its mask .

<p class="c-rate">
   <svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
      <use href="#star" mask="url(#half)" fill="green"></use>
      <use href="#star" fill="none" stroke="grey"></use>
   </svg>
</p>

Note that we have two <use> elements. One with mask , and one with stroke . This is how to use SVG masks to achieve contour styles.

address: 1614e6d94b299f https://codepen.io/shadeed/pen/jOmoaQQ

SVG gradient to achieve contour style

For the gradient solution, we don't need to copy the icon because there is no mask . What we need to do is add a stroke and it is done.

<svg style="width: 0; height: 0;" viewBox="0 0 32 32">
   <defs>
      <linearGradient id="half" x1="0" x2="100%" y1="0" y2="0">
        <stop offset="50%" stop-color="#f7efc5"></stop>
        <stop offset="50%" stop-color="#fed94b"></stop>
      </linearGradient>
   </defs>
</svg>

<p class="c-rate">
   <svg class="c-icon" width="32" height="32" viewBox="0 0 32 32">
     <use href="#star" fill="url(#half)" stroke="grey"></use>
   </svg>
</p>

Business address: https://codepen.io/shadeed/pen/QWvROVV

size

By using CSS variables and ensuring that the SVG has the correct viewBox attributes, we can easily resize them.

.c-icon {
    width: var(--size, 24px)
    height: var(--size, 24px);
}

.c-icon--md {
    --size: 40px;
}

.c-icon--lg {
    --size: 64px;
}

~End, I’m Shuwanzhi, I’m going to the SPA, see you next time~


Original: https://ishadeed.com/article/star-rating-svg/

possible bugs after 1614e6d94b2b2c code are deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time was spent on log debugging. By the way, I would like to recommend a useful BUG monitoring tool Fundebug .

comminicate

The article is continuously updated every week, and you can search for [Daqiang World] Read it for the first time and reply to [Welfare] are many front-end videos waiting for you. This article GitHub https://github.com/xiaozhiqq449245884 has been included, welcome to Star.

阅读 1k

终身学习者
我要先坚持分享20年,大家来一起见证吧。
62.9k 声望
95k 粉丝
0 条评论
62.9k 声望
95k 粉丝
文章目录
宣传栏