共计 5696 个字符,预计需要花费 15 分钟才能阅读完成。
星级展现应该是个挺常见的需要,刚好我的项目中有碰到。所以分享一下实现的过程,不便当前复用
一、需要剖析
先看个常见的星级展现 UI
剖析组件须要的参数
属性 | 含意 | 默认值 | 类型 |
---|---|---|---|
value | 以后星级 | 4.5 |
Number |
maxValue | 总星级 | 5 |
Number |
activeColor | 星级色彩 | #ff7e28 |
String |
先看「以后星级」这个参数,思考到有小数。所以不能用半星、全星之类的简略办法。
图示里的 4.3
示意前 4 个星星都齐全展现,最初一个展现宽度的 0.3
。所以咱们构建一个父子关系,让高亮局部的宽度,按父元素宽度的百分比展现即可
为了管制「星级色彩」,倡议用 svg 或者 font-icon(用图片也能够,多加两个参数传 activeImage
、placeholderImage
就行)
二、筹备图标
先找个星星图标。我是在 iconfont 上找的。过程不赘述了,间接帖代码
/* icon-star.css */
@font-face {
font-family: "iconfont";
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAALcAAsAAAAABogAAAKNAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGVgCCcAqBCIERATYCJAMICwYABCAFhGcHMhvFBci+QDaGA61+ohmjWdUpRTi3djdG3vv+AydFVwwi+NoP3Xd3AQDFIBMXDWjjomJJRrYKAHVlJ7a6QkUXbf2//7U2h1mHNAnaykXU02lemf9XdHawZqFapfEojUazRCPehY40QHws1yy4q+8HVWZx/WBKLK7PSs3l5Ym0eW581PWGkt85n+dyfAvogNYHsbtrbRprc9Q7oPJAOtDmtrEIe5En3jB2wQu8RKDRklUDm7vHLZg5dSSDOUPs3iBrjNNQOzDGo4oCC/VCbcPKIv5Dup0C7kSfj3/qMUZSk9ktOyc7Pry84IzJl9Wl5RuXy4WBrZExBxTioDG7ZVAwdlBjdsgIOFZj8FNVBR5xVKdgf51d3wyGYS74yZMftZDgsQaaAtYmtRBTte963PSzq+7WbZR++rG3cy+5z8/7ug/25y+g4Qk+6Mun4R/12ePXZ5/6/npxvuf7/kj6LfYsJntdN/3Irfrfx5TpT9GwDlCVHzMCwVs+PGb9sckCbrpfR+GqAsP81O/cG/wks4EdxVBsdyqa1NidTJ3c0OgkqNjBTt9TbV13VAz1uib46wxlyOqNEIWZQY0mK6hVbwONZu2sb9KlMChKAybcAIR2z0hafUPW7pUozBdq9OqjVrt/NDqKlt2aTIS3xeQI+eheYOjlmXKtEmltkD5JHK5LdYirECbQNqxyYY8y4jnmVKe6LqJQcZ7iLj2PkiTHgvOIPDECkWLRNFXTWwwvT2ELIw5BfMh1AYU8uYwK1KX4fQ1EO5Fw8ECik2WVEGpHNoM1gNgzZYPaHmSfyimtTggFKQzyKbTLh5FEIoeK5mER4hGGYEK6sMh01NRQk7G9Jf21fdDItqdwKrP6yzDTnhMAAAAA') 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";}
新建一个 icon-star.css
文件,把代码帖进去。vue 文件引入之后,在任意标签上加两个属性,就能够展现出咱们须要的「星星」了
<template>
<div class="iconfont icon-star"> 星星 </div>
</template>
<script>
import "./icon-star.css";
export default {}
</script>
三、代码编写
先实现一个能够展现指定宽度的星星
<template>
<div>
<div class="iconfont icon-star star-item star-placeholder">
<div
class="iconfont icon-star star-item star-active"
:style="{width:'60%'}"
/>
</div>
星星
</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+QDaGA61+ohmjWdUpRTi3djdG3vv+AydFVwwi+NoP3Xd3AQDFIBMXDWjjomJJRrYKAHVlJ7a6QkUXbf2//7U2h1mHNAnaykXU02lemf9XdHawZqFapfEojUazRCPehY40QHws1yy4q+8HVWZx/WBKLK7PSs3l5Ym0eW581PWGkt85n+dyfAvogNYHsbtrbRprc9Q7oPJAOtDmtrEIe5En3jB2wQu8RKDRklUDm7vHLZg5dSSDOUPs3iBrjNNQOzDGo4oCC/VCbcPKIv5Dup0C7kSfj3/qMUZSk9ktOyc7Pry84IzJl9Wl5RuXy4WBrZExBxTioDG7ZVAwdlBjdsgIOFZj8FNVBR5xVKdgf51d3wyGYS74yZMftZDgsQaaAtYmtRBTte963PSzq+7WbZR++rG3cy+5z8/7ug/25y+g4Qk+6Mun4R/12ePXZ5/6/npxvuf7/kj6LfYsJntdN/3Irfrfx5TpT9GwDlCVHzMCwVs+PGb9sckCbrpfR+GqAsP81O/cG/wks4EdxVBsdyqa1NidTJ3c0OgkqNjBTt9TbV13VAz1uib46wxlyOqNEIWZQY0mK6hVbwONZu2sb9KlMChKAybcAIR2z0hafUPW7pUozBdq9OqjVrt/NDqKlt2aTIS3xeQI+eheYOjlmXKtEmltkD5JHK5LdYirECbQNqxyYY8y4jnmVKe6LqJQcZ7iLj2PkiTHgvOIPDECkWLRNFXTWwwvT2ELIw5BfMh1AYU8uYwK1KX4fQ1EO5Fw8ECik2WVEGpHNoM1gNgzZYPaHmSfyimtTggFKQzyKbTLh5FEIoeK5mER4hGGYEK6sMh01NRQk7G9Jf21fdDItqdwKrP6yzDTnhMAAAAA")
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>
再加个循环,并计算每个 star-item
该展现的宽度。最终代码如下:
<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>
四、成果展现
<star-level :value="4.1" />
<star-level :value="3" activeColor="blue" />
<star-level :value="8.8" :maxValue="10" activeColor="green" />
五、抉择星级
既然展现都做进去了,不如再略微改改,做个抉择星级的组件
思路就是判断鼠标在以后星级的地位,并联合这是第几颗星,计算出 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>
附录:
CodeSandBox 代码示例:https://codesandbox.io/s/star…
正文完
发表至: javascript
2021-05-27