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>
相关推荐
honey ball12 分钟前
EMC内参二(1-33页)学习【技术进阶】
开发语言·单片机·嵌入式硬件·学习
森叶13 分钟前
利用本地 Express Web 服务解决复杂的 Electron 通信链路的问题
前端·electron·express
程序员老茶15 分钟前
C++:函数
开发语言·c++
土豆丶杨18 分钟前
vue3+electron 桌面应用初始化
javascript·vue.js·electron
我真的不会C21 分钟前
Qt中的多种输出方式,信号与槽的基本使用
开发语言·qt
阿巴阿巴拉42 分钟前
Scala相关知识学习总结5
开发语言·学习·scala
雪山青木1 小时前
php-cgi参数注入攻击经历浅谈
开发语言·网络安全·阿里云·php
冴羽1 小时前
SvelteKit 最新中文文档教程(18)—— 浅层路由和 Packaging
前端·javascript·svelte
双叶8361 小时前
(51单片机)矩阵按键密码锁表白(C语言代码编撰)(矩阵按键教程)(LCD1602浅教程)
c语言·开发语言·c++·算法·游戏·矩阵·51单片机
哀木1 小时前
聊聊前端埋点 clarity:我会一直视监你... 永远...
前端