Star display should be a very common requirement, just encountered in the project. So share the realization of the process, convenient reuse later

I. Demand analysis

Let’s start with a common star display UI

Analyze the parameters required by the component

attribute * * * * meanings The default value type
value The current star 4.5 Number
maxValue Total star 5 Number
activeColor Star color #ff7e28 String

First look at the “current star” parameter, allowing for decimals. So we can’t use half star, full star and so on simple method. The figure 4.3 shows that the first four stars are fully displayed, and the last one shows a width of 0.3. So we build a parent-child relationship where the width of the highlighted part is shown as a percentage of the width of the parent element

PlaceholderImage/webdb/webDb/webDb/webDb/webDb/webDb/webDb/webDb/webDb

Two, prepare the icon

Let’s start with a star. I looked it up on Iconfont. The process is not described, directly post code

/* icon-star.css */
@font-face {
  font-family: "iconfont";
  src: url('data:application/x-font-woff2; charset=utf-8; base64,d09GMgABAAAAAALcAAsAAAAABogAAAKNAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGVgCCcAqBCIERATYCJAMICwYABCAFhGcHMhvFBci+QDaGA 61+ohmjWdUpRTi3djdG3vv+AydFVwwi+NoP3Xd3AQDFIBMXDWjjomJJRrYKAHVlJ7a6QkUXbf2//7U2h1mHNAnaykXU02lemf9XdHawZqFapfEojUazRCPeh Y40QHws1yy4q+8HVWZx/WBKLK7PSs3l5Ym0eW581PWGkt85n+dyfAvogNYHsbtrbRprc9Q7oPJAOtDmtrEIe5En3jB2wQu8RKDRklUDm7vHLZg5dSSDOUPs3 iBrjNNQOzDGo4oCC/VCbcPKIv5Dup0C7kSfj3/qMUZSk9ktOyc7Pry84IzJl9Wl5RuXy4WBrZExBxTioDG7ZVAwdlBjdsgIOFZj8FNVBR5xVKdgf51d3wyGY S74yZMftZDgsQaaAtYmtRBTte963PSzq+7WbZR++rG3cy+5z8/7ug/25y+g4Qk+6Mun4R/12ePXZ5/6/npxvuf7/kj6LfYsJntdN/3Irfrfx5TpT9GwDlCVH zMCwVs+PGb9sckCbrpfR+GqAsP81O/cG/wks4EdxVBsdyqa1NidTJ3c0OgkqNjBTt9TbV13VAz1uib46wxlyOqNEIWZQY0mK6hVbwONZu2sb9KlMChKAybcA IR2z0hafUPW7pUozBdq9OqjVrt/NDqKlt2aTIS3xeQI+eheYOjlmXKtEmltkD5JHK5LdYirECbQNqxyYY8y4jnmVKe6LqJQcZ7iLj2PkiTHgvOIPDECkWLRN FXTWwwvT2ELIw5BfMh1AYU8uYwK1KX4fQ1EO5Fw8ECik2WVEGpHNoM1gNgzZYPaHmSfyimtTggFKQzyKbTLh5FEIoeK5mER4hGGYEK6sMh01NRQk7G9Jf21f dDItqdwKrP6yzDTnhMAAAAA') format('woff2')}.iconfont {
  font-family: "iconfont" ! important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-star:before {
  content: "\e627";
}

Copy the code

Create a new icon-star. CSS file and paste the code into it. Once the VUE file is introduced, we can add two attributes to any tag to show the “stars” we need

<template>
	<div class="iconfont icon-star">The stars</div>
</template>

<script>
import "./icon-star.css";
 
export default {}
</script>
Copy the code

Third, code writing

Implement a star that displays the specified width

<template>
  <div>
    <div class="iconfont icon-star star-item star-placeholder">
      <div
        class="iconfont icon-star star-item star-active"
        :style="{ width: '60%' }"
      />
    </div>The stars</div>
</template>

<script>
export default {};
</script>


<style scoped>
@font-face {
  font-family: "iconfont";
  src: url("data:application/x-font-woff2; charset=utf-8; base64,d09GMgABAAAAAALcAAsAAAAABogAAAKNAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGVgCCcAqBCIERATYCJAMICwYABCAFhGcHMhvFBci+QDaGA 61+ohmjWdUpRTi3djdG3vv+AydFVwwi+NoP3Xd3AQDFIBMXDWjjomJJRrYKAHVlJ7a6QkUXbf2//7U2h1mHNAnaykXU02lemf9XdHawZqFapfEojUazRCPeh Y40QHws1yy4q+8HVWZx/WBKLK7PSs3l5Ym0eW581PWGkt85n+dyfAvogNYHsbtrbRprc9Q7oPJAOtDmtrEIe5En3jB2wQu8RKDRklUDm7vHLZg5dSSDOUPs3 iBrjNNQOzDGo4oCC/VCbcPKIv5Dup0C7kSfj3/qMUZSk9ktOyc7Pry84IzJl9Wl5RuXy4WBrZExBxTioDG7ZVAwdlBjdsgIOFZj8FNVBR5xVKdgf51d3wyGY S74yZMftZDgsQaaAtYmtRBTte963PSzq+7WbZR++rG3cy+5z8/7ug/25y+g4Qk+6Mun4R/12ePXZ5/6/npxvuf7/kj6LfYsJntdN/3Irfrfx5TpT9GwDlCVH zMCwVs+PGb9sckCbrpfR+GqAsP81O/cG/wks4EdxVBsdyqa1NidTJ3c0OgkqNjBTt9TbV13VAz1uib46wxlyOqNEIWZQY0mK6hVbwONZu2sb9KlMChKAybcA IR2z0hafUPW7pUozBdq9OqjVrt/NDqKlt2aTIS3xeQI+eheYOjlmXKtEmltkD5JHK5LdYirECbQNqxyYY8y4jnmVKe6LqJQcZ7iLj2PkiTHgvOIPDECkWLRN FXTWwwvT2ELIw5BfMh1AYU8uYwK1KX4fQ1EO5Fw8ECik2WVEGpHNoM1gNgzZYPaHmSfyimtTggFKQzyKbTLh5FEIoeK5mER4hGGYEK6sMh01NRQk7G9Jf21f dDItqdwKrP6yzDTnhMAAAAA")
    format("woff2");
}

.iconfont {
  font-family: "iconfont" ! important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-star:before {
  content: "\e627";
}

.star-item {
  display: inline-block;
  font-size: 40px;
}

.star-placeholder {
  position: relative;
}
.star-active {
  position: absolute;
  top: 0;
  left: 0;
  color: red;
  overflow: hidden;
}
</style>

Copy the code

Add another loop and calculate the width of the display for each star-item. The final code is as follows:

<template>
  <div>
    <div
      v-for="index in maxValue"
      :key="index"
      class="iconfont icon-star star-item star-placeholder"
    >
      <div
        class="iconfont icon-star star-item star-active"
        :style="{ width: getWidth(index), color: activeColor }"
      />
    </div>
    <span class="star-value">
      {{ starValue }}
    </span>
  </div>
</template>

<script>
import "./icon-star.css";

export default {
  props: {
    maxValue: {
      type: Number.default: 5,},value: {
      type: Number.default: 4.5,},activeColor: {
      type: String.default: "#ff7e28",}},computed: {
    starValue() {
      return this.value.toFixed(1); }},methods: {
    getWidth(index) {
      const gap = this.value - index + 1;
      if (gap >= 1) {
        return "100%";
      } else if (gap <= 0) {
        return 0;
      } else {
        return gap * 100 + "%"; ,}}}};</script>


<style scoped>
.star-item {
  display: inline-block;
  font-size: 40px;
}

.star-placeholder {
  position: relative;
  color: #e9e9e9;
}
.star-active {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
}
.star-value {
  font-size: 40px;
  margin-left: 10px;
}
</style>

Copy the code

Iv. Effect display

  <star-level :value="4.1" />
  <star-level :value="3" activeColor="blue" />
  <star-level :value="8.8" :maxValue="10" activeColor="green" />
Copy the code

Five, choose stars

Now that the presentation has been made, it is better to modify it slightly and make a selection of star components

The idea is to judge the mouse in the current star position, and combined with the number of stars, calculate the value

<template>
  <div>
    <div
      v-for="index in maxValue"
      :key="index"
      @mousemove="mousemoveStarItem($event, index)"
      class="iconfont icon-star star-item star-placeholder"
    >
      <div
        class="iconfont icon-star star-item star-active"
        :style="{ width: getWidth(index), color: activeColor }"
      />
    </div>
    <span class="star-value" :style="{ color: activeColor }">
      {{ starValue }}
    </span>
  </div>
</template>

<script>
import "./icon-star.css";

export default {
  data() {
    return {
      value: 0}; },props: {
    maxValue: {
      type: Number.default: 5,},activeColor: {
      type: String.default: "#ff7e28",}},computed: {
    starValue() {
      return this.value.toFixed(1); }},methods: {
    getWidth(index) {
      const gap = this.value - index + 1;
      if (gap >= 1) {
        return "100%";
      } else if (gap <= 0) {
        return 0;
      } else {
        return gap * 100 + "%"; }},mousemoveStarItem(e, index) {
      const width = e.currentTarget.offsetWidth;
      this.value = index + e.offsetX / width - 1; ,}}};</script>


<style scoped>
.star-item {
  display: inline-block;
  font-size: 40px;
}

.star-placeholder {
  cursor: pointer;
  position: relative;
  color: #e9e9e9;
}
.star-active {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
}
.star-value {
  font-size: 40px;
  margin-left: 10px;
}
</style>

Copy the code

Appendix:

CodeSandBox Code example: codesandbox.io/s/start-lev…