自定义区间滑块

自定义区间滑块


需求:用户在滑块上能够左右滑动滑点,进行区间值的筛选

效果示例图

在这里插入图片描述

代码块

<template>
	<view class="slider-wrap">
		<view class="slider-start">{{ startValue }}</view>
		<view style="width: 8px;"></view>
		<view class="slider-progress">
			<view class="slider-range" id="sliderRange" :style="{ width: sliderWidth + 'px' }">
				<view class="rangeBox" :style="{ width: rangeWidth + 'px', left: minLeft + 'px' }"></view>
				<view class="slider-lf" :style="{ left: minLeft + 'px' }" @touchstart="startTouchStartHandle" @touchmove="startTouchmoveHandle" @touchend="startTouchEndHandle">
					<text></text>
				</view>
				<view class="slider-rg" :style="{ left: maxLeft + 'px' }" @touchstart="endTouchStartHandle" @touchmove="endTouchmoveHandle" @touchend="endTouchEndHandle">
					<text></text>
				</view>
			</view>
		</view>
		<view style="width: 8px;"></view>
		<view class="slider-end">{{ endValue }}</view>
	</view>
</template>

<script>
let minInitX = 0;
let minInitLeft = 0;

let maxInitX = 0;
let maxInitLeft = 0;
export default {
	data() {
		return {
			//默认值
			defaultMin: 3,
			defaultMax: 6,
			//起始值
			startValue: 2,
			//结束值
			endValue: 7,
			//滑块的最大宽度
			sliderWidth: 180,
			//滑块之间最小间距,这个大小根据页面显示圆点大小设置
			minSpace: 24,

			//两个滑点之间的距离
			rangeWidth: 180,
			//左边滑点距离左边的距离
			minLeft: 0,
			//右边滑点距离左边的距离
			maxLeft: 180
		};
	},
	onShow() {
		this.initSlider();
	},
	methods: {
		/**
		 * 初始化数据
		 * **/
		initSlider() {
			//如果最大值小于等于最小值,就默认最大值100,最小值0
			if (this.endValue <= this.startValue) {
				this.startValue = 0;
				this.endValue = 100;
			}
			if (this.defaultMin == 'null' || this.defaultMin == undefined || this.defaultMin == '') {
				this.defaultMin = this.startValue;
			}
			if (this.defaultMax == 'null' || this.defaultMax == undefined || this.defaultMax == '') {
				this.defaultMax = this.endValue;
			}
			//如果默认传值错误,就把默认传值设置成最大值,最小值
			if (this.defaultMax <= this.defaultMin) {
				this.defaultMin = this.startValue;
				this.defaultMax = this.endValue;
			}
			if (this.defaultMin < this.startValue) {
				this.defaultMin = this.startValue;
			}
			if (this.defaultMax > this.endValue) {
				this.defaultMax = this.endValue;
			}

			this.minLeft = ((this.defaultMin - this.startValue) / (this.endValue - this.startValue)) * this.sliderWidth;
			this.maxLeft = ((this.defaultMax - this.startValue) / (this.endValue - this.startValue)) * this.sliderWidth;
			this.rangeWidth = this.maxLeft - this.minLeft;
		},
		/**
		 * min
		 * **/
		startTouchStartHandle(e) {
			//初始化鼠标开始拖拽的点击位置
			minInitX = e.touches[0].clientX;
			//获取滑块当前的位置
			minInitLeft = e.currentTarget.offsetLeft;
		},
		startTouchmoveHandle(e) {
			//获取鼠标移动后滑块应该移动到的位置
			let nX = e.touches[0].clientX - minInitX + minInitLeft;
			if (nX >= this.maxLeft - this.minSpace) {
				nX = this.maxLeft - this.minSpace;
			}
			if (nX < 0) {
				nX = 0;
			}
			this.minLeft = nX;
			this.rangeWidth = this.maxLeft - this.minLeft;
		},
		startTouchEndHandle(e) {
			this.changeRangeFun(this.minLeft, this.maxLeft);
			e.stopPropagation();
		},
		/**
		 * max
		 * **/
		endTouchStartHandle(e) {
			//初始化鼠标开始拖拽的点击位置
			maxInitX = e.touches[0].clientX;
			//获取滑块当前的位置
			maxInitLeft = e.currentTarget.offsetLeft;
		},
		endTouchmoveHandle(e) {
			//获取鼠标移动后滑块应该移动到的位置
			let nX = e.touches[0].clientX - maxInitX + maxInitLeft;
			if (nX >= this.sliderWidth) {
				nX = this.sliderWidth;
			}
			if (nX <= this.minLeft + this.minSpace) {
				nX = this.minLeft + this.minSpace;
			}
			this.maxLeft = nX;
			this.rangeWidth = this.maxLeft - this.minLeft;
		},
		endTouchEndHandle(e) {
			this.changeRangeFun(this.minLeft, this.maxLeft);
			e.stopPropagation();
		},
		/**
		 * 改变中间的距离线大小
		 * **/
		changeRangeFun(min, max) {
			const startValue = this.startValue;
			const endValue = this.endValue;
			let tempArr = [];
			for (let i = startValue; i <= endValue; i++) {
				tempArr.push(i);
			}

			//把滑动条距离分割
			const sliderWidth = this.sliderWidth;
			const part = sliderWidth / tempArr.length;

			let minIndex = Math.trunc(min / part) - 1 < 0 ? 0 : Math.trunc(min / part) - 1;
			let maxIndex = Math.trunc(max / part) - 1 < 1 ? 1 : Math.trunc(max / part) - 1;

			const minValue = tempArr[minIndex];
			const maxValue = tempArr[maxIndex];

			console.log('[最终区间值]', minValue, maxValue);
			this.defaultMin = minValue;
			this.defaultMax = maxValue;
		}
	}
};
</script>

<style lang="scss" scoped>
// slider
.slider-wrap {
	display: flex;
	flex-direction: row;

	.slider-start,
	.slider-end {
		width: 60px;
		height: 36px;
		background: #2c3b45;
		border-radius: 18px;
		font-size: 15px;
		font-family: Source Han Sans CN;
		font-weight: bold;
		color: #ffffff;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.slider-progress {
		flex: 1;
		display: flex;
		flex-direction: row;
		position: relative;
		height: 36px;
		align-items: center;
		justify-content: center;

		.slider-range {
			width: 190px;
			height: 10px;
			background: #2c3b45;
			border-radius: 4px;
			position: relative;

			.rangeBox {
				width: 100%;
				height: 10px;
				background: linear-gradient(90deg, #1be6bd 0%, #00a8f6 100%);
				border-radius: 4px;
				position: absolute;
				top: 0px;
			}

			.slider-lf {
				width: 24px;
				height: 24px;
				background: linear-gradient(90deg, #1be6bd 0%, #00a8f6 100%);
				border-radius: 50%;
				position: absolute;
				top: -7px;
				display: flex;
				justify-content: center;
				align-items: center;
				transform: translateX(-12px);

				text {
					width: 10px;
					height: 10px;
					background: #ffffff;
					border-radius: 50%;
				}
			}

			.slider-rg {
				width: 24px;
				height: 24px;
				background: linear-gradient(90deg, #1be6bd 0%, #00a8f6 100%);
				border-radius: 50%;
				position: absolute;
				top: -7px;
				display: flex;
				justify-content: center;
				align-items: center;
				transform: translateX(-12px);

				text {
					width: 10px;
					height: 10px;
					background: #ffffff;
					border-radius: 50%;
				}
			}
		}
	}
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值