大致逻辑是 使用两个标签 用第二行标签覆盖第一行的标签,其中第一行为未选中状态,第二行为点亮状态。再通过calc 根据传入的百分比计算第二行要显示的宽度,溢出隐藏。这样就可以实现评分点亮的状态,以及亮半星 或 亮3分之一等。
如图一 把第红色那一行覆盖前一行
如总评分为10分 当评分为8.4时 评分组件就显示如下红色行状态
具体代码如下:
<view class="um-rate">
<view class="rate-default" style="column-gap: {{gutter}}px;">
<view class="rate-item" wx:for="{{rates}}" wx:key="item" bindtap="changeRate" data-index="{{index}}">
<um-icon type="jiansheyinhang" size="{{size}}" color="{{voidColor}}" />
</view>
</view>
<view class="rate-active" style="column-gap: {{gutter}}px;width:calc({{percent + '%'}})">
<view wx:for="{{rates}}" wx:key="item" bindtap="changeRate" data-index="{{index}}">
<um-icon type="jiansheyinhang" size="{{size}}" color="{{color}}" />
</view>
</view>
</view>
// components/um-rate/index.js
import { getNodes } from '../../utils/util'
Component({
/**
* 组件的属性列表
*/
properties: {
value: {
type: Number,
value: 0
},
totalValue: {
type: Number,
value: 5
},
count: {
type: Number,
value: 5
},
size: {
type: Number,
value: 16
},
gutter: {
type: Number,
value: 4
},
icon: {
type: String,
value: 'star'
},
color: {
type: String,
value: '#ffd21e'
},
voidColor: {
type: String,
value: '#c7c7c7'
},
disabled: {
type: Boolean,
default: false
}
},
/**
* 组件的初始数据
*/
data: {
},
observers: {
value(value) {
let { gutter, count, totalValue } = this.properties
if (value > totalValue) value = totalValue
this.setData({
percent: value / totalValue * 100,
interval: gutter / count
})
}
},
/**
* 组件的方法列表
*/
methods: {
changeRate(e) {
if (this.properties.disabled) return
let { index } = e.currentTarget.dataset
this.setData({
value: ++index
}, () => {
this.triggerEvent('change', this.data.value)
})
}
},
lifetimes: {
attached() {
const { count } = this.properties
let rates = []
for (let i = 1; i <= count; i++) {
rates.push(i)
}
this.setData({
rates
})
}
}
})
/* components/um-rate/index.wxss */
.um-rate{
position: relative;
display: inline-block
}
.rate-active,
.rate-default {
position: relative;
display: flex;
}
.rate-active{
position: absolute;
left: 0;
top: 0;
width: 0;
overflow: hidden;
transition:all .3s;
}