This commit is contained in:
2025-10-27 15:55:29 +08:00
commit 6632080b83
513 changed files with 117442 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
export function getClientRect(selector, component) {
return new Promise((resolve, reject) => {
let query = component ? uni.createSelectorQuery().in(component) : uni.createSelectorQuery();
return query.select(selector).boundingClientRect(resolve).exec()
})
}

View File

@@ -0,0 +1,218 @@
<template>
<view class="rate-box" :class="[{ animation }, containerClass]" @touchmove="ontouchmove" @touchend="touchMoving = false">
<view
v-for="(val, i) in list"
:key="val"
class="rate"
:style="{ fontSize, paddingLeft: i !== 0 ? rateMargin : 0, paddingRight: i < list.length - 1 ? rateMargin : 0 }"
:class="[
{ scale: !disabled && val <= rateValue && animation && touchMoving, 'color-base-text': val <= rateValue, defaultColor: val > rateValue },
`rate-${i}`,
rateClass
]"
:data-val="val"
@click="onItemClick"
>
<text class="iconfont icon-star"></text>
</view>
</view>
</template>
<script>
import { getClientRect } from './common';
export default {
name: 'sx-rate',
props: {
// 当前值
value: {
type: [Number, String]
},
// 最大星星数量
max: {
type: Number,
default: 5
},
// 禁用
disabled: {
type: Boolean,
default: false
},
// 动画效果
animation: {
type: Boolean,
default: true
},
// 默认星星颜色
defaultColor: {
type: String,
default: '#ccc'
},
// 滑选后星星颜色
activeColor: {
type: String
// default: '#FFB700'
},
// 星星大小
fontSize: {
type: String,
default: 'inherit'
},
// 星星间距
margin: {
type: String,
default: ''
},
// 自定义类名-容器
containerClass: {
type: String,
default: ''
},
// 自定义类名-星星
rateClass: {
type: String,
default: ''
},
index: {
// 如果页面中存在多个该组件,通过该属性区分
type: [Number, String]
}
},
data() {
return {
rateValue: 0,
touchMoving: false,
startX: [],
startW: 30
};
},
computed: {
list() {
return [...new Array(this.max)].map((_, i) => i + 1);
},
rateMargin() {
let margin = this.margin;
if (!margin) return 0;
switch (typeof margin) {
case 'number':
margin = margin * 2 + 'rpx';
case 'string':
break;
default:
return 0;
}
let reg = /^(\d+)([^\d]*)/;
let result = reg.exec(margin);
if (!result) return 0;
let [_, num, unit] = result;
return num / 2 + unit;
}
},
watch: {
value: {
handler(val) {
this.rateValue = val;
},
immediate: true
}
},
methods: {
// 计算星星位置
async initStartX() {
let { max } = this;
this.startX = [];
for (let i = 0; i < max; i++) {
let selector = `.rate-${i}`;
let { left, width } = await getClientRect(selector, this);
this.startX.push(left);
this.startW = width;
}
},
/**
* 手指滑动事件回调
* https://github.com/sunxi1997/uni-app-sx-rate/pull/1
* 原本的触摸处理在自定了样式后可能会出现bug, 已解决
*/
async ontouchmove(e) {
if (!this.touchMoving) {
this.touchMoving = true;
// 开始手指滑动时重新计算星星位置,防止星星位置意外变化
await this.initStartX();
}
let { startX, startW, max } = this;
let { touches } = e;
// 触摸焦点停留的位置
let { pageX } = touches[touches.length - 1];
// 超出最左边, 0 星
if (pageX <= startX[0]) return this.toggle(0);
// 刚好在第一颗星
else if (pageX <= startX[0] + startW) return this.toggle(1);
// 超出最右边, 最大星
else if (pageX >= startX[max - 1]) return this.toggle(max);
//计算星星停留的位置
let startXHash = startX.concat(pageX).sort((a, b) => a - b);
this.toggle(startXHash.indexOf(pageX));
},
// 点击回调
onItemClick(e) {
let { val } = e.currentTarget.dataset;
this.toggle(val);
},
// 修改值
toggle(val) {
let { disabled } = this;
if (disabled) return;
if (this.rateValue !== val) {
this.rateValue = val;
this.$emit('update:value', val);
let data = {
index: this.index,
value: val
};
this.$emit('change', data);
}
}
},
mounted() {}
};
</script>
<style scoped>
@import './sx-rate/iconfont.css';
</style>
<style lang="scss">
.rate-box {
min-height: 1.4em;
display: flex;
align-items: center;
}
.rate {
display: inline-flex;
justify-content: center;
align-items: center;
width: 1.2em;
transition: all 0.15s linear;
}
.rate.scale {
transform: scale(1.1);
}
.defaultColor {
color: #ccc !important;
}
.activeColor {
}
</style>

View File

@@ -0,0 +1,21 @@
@font-face {font-family: "iconfont";
src: url('~@/pages_tool/components/sx-rate/sx-rate/iconfont.eot?t=1574760464482'); /* IE9 */
src: url('~@/pages_tool/components/sx-rate/sx-rate/iconfont.eot?t=1574760464482#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAK8AAsAAAAABnAAAAJwAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcAp8gQgBNgIkAwgLBgAEIAWEbQcuG6wFyA4lTcHACOEZBUg8fL/2O3f3fTHEkoh28SSayCSxkkgQG6Uz3UvYITu9Qr5K0Vh6Ij6f+8CXKzVBHDvWa6d0lSfK57mc3gQ6kGt8oBz3ojUG9QLqxYEU6B4YRVYqecPYBS7hMYG6QWF0dlOycoGxxFoViFuxkALGuYAksXRVKNccTOJdSTV7zbSAt/D78Y8XxmRKOavq5CZZAOK+7u2svLVode0TggR0vIQc84BEXNQmjugJxumpJ/SNAvsqD77ui8K3i71aBPvrrNIm6IfSe5K58ltNZ3BbU40Blkf9OmKsIW/Un1qddc4dcSma3ArIX7PPXdlxK5l2zJ+aD6TXnQqmu330wqpeWkYN/OnNm/0trU+YvqNR4UN99f+x/tApIFTfR7u39X4gKPnb9pOX5RAQB6DYyc/zOKCD4OUp6KiiPeqnapbAp56NdegrdhLo5wKq+3UG/0fWcyDpCsuWJVVWO5oZO29bXR0FwJ4uV2ONvTeTCVW9I1wVAylyVeNkYudR0rCOsqoN1M1JPd7QDdMTqYZZXQChwwYybT6Q63BIJvYSJX1eUNYReqi7CrsLGyZDbJqIEUWQAPLroJhWKhjHQUyj8mwkrJJROKsI+XyENeIw5LI4xXQqUiA8xxZNtZBHCAMZrJTDFPAcksmUUIWVEkQTlogQVQSbzdS9iUUr5cDUDgyhEIgAxFcHEqMpKTD+eMK09PlsiFAVGQpu6atJ5kMwDfHsEBcLpweZqlX06ruXVzSqCfEQBANiYEpyUAqYh8jIKEGq+nkSCI1gEY2IqURg28OYvlrW+nr5152AOsuUhV2fSy+EwgAAAA==') format('woff2'),
url('~@/pages_tool/components/sx-rate/sx-rate/iconfont.woff?t=1574760464482') format('woff'),
url('~@/pages_tool/components/sx-rate/sx-rate/iconfont.ttf?t=1574760464482') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('~@/pages_tool/components/sx-rate/sx-rate/iconfont.svg?t=1574760464482#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: inherit;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-star:before {
content: "\e6e3";
}

Binary file not shown.

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="star" unicode="&#59107;" d="M544.256 812.032l117.248-237.568c5.12-10.752 15.36-17.92 27.136-19.456l262.144-37.888c29.696-4.096 41.472-40.448 19.968-61.44l-189.44-184.832c-8.704-8.192-12.288-19.968-10.24-31.744l44.544-261.12c5.12-29.184-25.6-51.712-52.224-37.888l-234.496 123.392c-10.24 5.632-23.04 5.632-33.28 0L261.12-59.904c-26.112-13.824-57.344 8.704-52.224 37.888l44.544 261.12c2.048 11.776-2.048 23.552-10.24 31.744L53.76 455.68C32.256 476.16 44.032 512.512 73.728 517.12l262.144 37.888c11.776 1.536 22.016 9.216 27.136 19.456l117.248 237.568C493.056 838.656 530.944 838.656 544.256 812.032z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.