uniapp滚动尺
- 手机
- 2025-08-27 01:48:02

scale组件代码(部分class样式使用到了uview1.0的样式)
<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> <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> <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>使用方式
<script> import Scale from '@/components/Scale/index.vue'; export default { components: { Scale }, data() { return { value:'10.0', } }, } </script> <view class="value"> <text>{{value}}</text> </view> <scale v-model="value" :width="16"></scale> <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>