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>
相关推荐
爱编程的小庄20 分钟前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成36 分钟前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
秋窗740 分钟前
Mac下Python版本管理,适用于pyenv不起作用的情况
开发语言·python·macos
柯腾啊43 分钟前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段
Jay丶萧邦1 小时前
el-select:有关多选,options选项值不包含绑定值的回显问题
javascript·vue.js·elementui
weixin_535854221 小时前
oppo,汤臣倍健,康冠科技,高途教育25届春招内推
c语言·前端·嵌入式硬件·硬件工程·求职招聘
扣丁梦想家1 小时前
设计模式教程:装饰器模式(Decorator Pattern)
java·前端·装饰器模式
CoderIsArt1 小时前
openGL和C#下使用openGL
开发语言·c#
pixle01 小时前
Three.js 快速入门教程【一】开启你的 3D Web 开发之旅
前端·javascript·3d
@PHARAOH2 小时前
HOW - 服务接口超时时间和建议策略
前端·接口·接口超时