<template>
<view class="u-rate" :id="elId" @touchmove.stop.prevent="touchMove">
<view class="u-star-wrap" v-for="(item, index) in count" :key="index" :class="[elClass]">
<u-icon
v-if="!activeSrc || !inactiveSrc"
@click="click(index + 1, $event)"
:name="activeIndex > index ? activeIcon : inactiveIcon"
:color="activeIndex > index ? activeColor : inactiveColor"
:style="{
fontSize: size + 'rpx',
padding: `0 ${gutter / 2 + 'rpx'}`
}"
></u-icon>
<image v-else @click="click(index + 1, $event)" :style="{
width: width + 'rpx',
height: height + 'rpx',
padding: `0 ${gutter + 'rpx'}`
}" :src="activeIndex > index ? activeSrc : inactiveSrc" ></image>
</view>
</view>
</template>
<script>
export default {
name: 'u-rate',
props: {
value: {
type: [Number, String],
default: -1
},
count: {
type: [Number, String],
default: 5
},
current: {
type: [Number, String],
default: 0
},
disabled: {
type: Boolean,
default: false
},
size: {
type: [Number, String],
default: 30
},
inactiveColor: {
type: String,
default: '#b2b2b2'
},
activeColor: {
type: String,
default: '#FA3534'
},
gutter: {
type: [Number, String],
default: 20
},
minCount: {
type: [Number, String],
default: 0
},
allowHalf: {
type: Boolean,
default: false
},
activeIcon: {
type: String,
default: 'star-fill'
},
inactiveIcon: {
type: String,
default: 'star'
},
width: {
type: [Number, String],
default: 15
},
height: {
type: [Number, String],
default: 15
},
activeSrc: {
type: String,
default: ''
},
inactiveSrc: {
type: String,
default: ''
},
},
data() {
return {
elId: this.$u.guid(),
elClass: this.$u.guid(),
starBoxLeft: 0,
activeIndex: this.value != -1 ? this.value : this.current,
starWidth: 0,
starWidthArr: []
}
},
watch: {
current(val) {
this.activeIndex = val
},
value(val) {
this.activeIndex = val
}
},
methods: {
getElRectById() {
this.$u.getRect('#' + this.elId).then(res => {
this.starBoxLeft = res.left
})
},
getElRectByClass() {
this.$u.getRect('.' + this.elClass).then(res => {
this.starWidth = res.width
for (let i = 0; i < this.count; i++) {
this.starWidthArr[i] = (i + 1) * this.starWidth
}
})
},
touchMove(e) {
if (this.disabled) {
return
}
if (!e.changedTouches[0]) {
return
}
const movePageX = e.changedTouches[0].pageX
const distance = movePageX - this.starBoxLeft
if (distance <= 0) {
this.activeIndex = 0
}
let index = Math.ceil(distance / this.starWidth)
this.activeIndex = index > this.count ? this.count : index
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount
this.emitEvent()
},
click(index, e) {
if (this.disabled) {
return
}
if (this.allowHalf) {
}
if (index == 1) {
if (this.activeIndex == 1) this.activeIndex = 0
else this.activeIndex = 1
} else {
this.activeIndex = index
}
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount
this.emitEvent()
},
emitEvent() {
this.$emit('change', this.activeIndex)
if (this.value != -1) {
this.$emit('input', this.activeIndex)
}
}
},
mounted() {
this.getElRectById()
this.getElRectByClass()
}
}
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.u-rate {
display: -webkit-inline-flex;
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
}
.u-icon {
box-sizing: border-box;
}
</style>