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…