
scale组件代码(部分class样式使用到了uview1.0的样式)
html
<template>
<view>
<view class="scale">
<view class="pointer u-flex-col u-col-center">
<u-icon name="arrow-down-fill" size="26" color="#33B4C2"></u-icon>
</view>
<view class="ruler">
<scroll-view class="scroll" :scroll-x="true" :scrollLeft="scrollLeft" @scroll="scaleScroll"
@touchstart="touchstart" @touchend="touchend">
<view class="u-col-top" style="display: inline-flex;padding: 0 calc(50%);">
<template v-for="(item,index) in scale">
<view :class="['line',item%10==0?'int':(item%5==0?'middle':'')]"
:style="{width: `${width}rpx`}" >
<view class="value" v-if="item%10==0">
<text>{{item/10}}</text>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
javascript
<script>
export default {
name: 'Scale',
components: {},
props: {
value: {
type: String,
default: '0.0'
},
// 最小值
min: {
type: Number,
default: 0,
},
// 最大值
max: {
type: Number,
default: 100,
},
// 每个刻度宽度
width: {
type: Number,
default: 10,
},
},
data() {
return {
scrollLeft: 0,//
left:0,//
isScroll: true,//用户是否停止操作
scrollTimer:null,
manual:false,
implement:false,//是否还在滚动
};
},
computed: {
scale() {
//计算出标尺所有刻度
let arr = [];
for (let i = this.min*10; i <= this.max * 10; i++) {
arr.push(i);
}
return arr;
},
widthPx(){
//每个刻度宽度
return uni.upx2px(this.width);
}
},
created() {
//数据回显
let val = parseFloat(this.value);
if(val<=this.min){
this.$emit('input',this.min.toFixed(1))
}else{
this.scroll()
}
},
methods: {
//滚动
scaleScroll(e) {
if(!this.manual){
return;
}
//还在滚动中
this.implement = true;
//获取滚动距离
let scrollLeft = e.detail.scrollLeft;
this.left = scrollLeft;
//计算对应值
let index = (scrollLeft / this.widthPx).toFixed(0);
let value = (this.scale[parseInt(index)]/10).toFixed(1);
this.$emit('input', value);
//避免重复执行@scroll
clearTimeout(this.scrollTimer);
this.scrollTimer = setTimeout(()=>{
//判断用户是否已经停止操作
if(this.isScroll){
this.scroll()
}
},300)
},
//开始滚动
touchstart(e) {
this.isScroll = false;
this.manual = true;
},
//用户停止操作
touchend(e) {
this.isScroll = true;
this.implement = false;
//解决scaleScroll已经执行完,但标尺未吸附问题
setTimeout(()=>{
//判断是否还在滚动并且是否已经吸附
if(this.left!=this.scrollLeft&&!this.implement){
this.scroll()
}
},300)
},
//标尺吸附
scroll(){
//吸附时禁止执行@scaleScroll,防止一直滚动,数据异常
this.manual = false;
//计算滚动距离
let index = this.scale.indexOf(parseInt(this.value*10));
this.scrollLeft = index * this.widthPx;
}
},
};
</script>
css
<style lang="scss" scoped>
.scale {
width: 100%;
.pointer {
position: relative;
padding-bottom: 12rpx;
&::after {
position: absolute;
z-index: 9;
top: 38rpx;
content: '';
display: block;
width: 4rpx;
height: 78rpx;
background: #33B4C2;
}
}
.ruler {
height: 114rpx;
.scroll {
height: 100%;
width: 100%;
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
.line {
position: relative;
height: 36rpx;
display: flex;
flex-direction: column;
align-items: center;
&:last-child{
width: 2rpx !important;
}
&::after {
content: '';
position: absolute;
display: block;
width: 2rpx;
height: 100%;
top: 0;
left: 0;
background: #C1E8ED;
}
.value {
left: -23rpx;
position: absolute;
bottom: -48rpx;
width: 46rpx;
height: 36rpx;
font-size: 26rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #C1C1C1;
line-height: 36rpx;
text-align: center;
}
}
.int {
height: 66rpx;
}
.middle {
height: 50rpx;
}
}
}
}
</style>
使用方式
javascript
<script>
import Scale from '@/components/Scale/index.vue';
export default {
components: {
Scale
},
data() {
return {
value:'10.0',
}
},
}
</script>
html
<view class="value">
<text>{{value}}</text>
</view>
<scale v-model="value" :width="16"></scale>
css
<style lang="scss">
.value{
padding: 36rpx 0 20rpx;
font-size: 36rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #33B4C2;
line-height: 50rpx;
text-align: center;
&::after{
content: ' 公斤';
height: 50rpx;
font-size: 24rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #33B4C2;
line-height: 50rpx;
}
}
</style>