uniapp 滚动尺

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>
相关推荐
好家伙VCC20 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
南极星100520 小时前
蓝桥杯JAVA--启蒙之路(十)class版本 模块
java·开发语言
未来之窗软件服务20 小时前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
baidu_2474386120 小时前
Android ViewModel定时任务
android·开发语言·javascript
嘿起屁儿整21 小时前
面试点(网络层面)
前端·网络
Dev7z21 小时前
基于 MATLAB 的铣削切削力建模与仿真
开发语言·matlab
不能隔夜的咖喱21 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头21 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
小天源21 小时前
Error 1053 Error 1067 服务“启动后立即停止” Java / Python 程序无法后台运行 windows nssm注册器下载与报错处理
开发语言·windows·python·nssm·error 1053·error 1067
有位神秘人21 小时前
Android中Notification的使用详解
android·java·javascript