SliderRange区间组件是一种用户界面(UI)元素,允许用户通过拖动滑块来选择一个数值范围。这种组件在多种应用程序和平台中广泛使用,组件已经测试兼容微信小程序、H5、App。以下是对SliderRange区间组件的详细介绍:
一、组件构成
SliderRange区间组件通常由以下部分构成:
滑动区域:用于显示滑动条的背景,通常是一个长条形的区域。
滑块:用户可以通过拖动滑块来改变数值范围。滑块可以是单个的,也可以是双个的,用于选择区间的起始和结束值。
二、主要功能和特点
数值范围选择:SliderRange区间组件允许用户选择一个数值范围,而不是单个数值。这使得它非常适合用于需要用户输入范围的应用场景,如价格筛选、音量调节等。
高度可定制性:许多SliderRange区间组件提供了丰富的配置选项,如颜色、大小、步长、方向等,以满足不同应用的需求。
响应式设计:许多SliderRange区间组件支持响应式设计,能够自适应不同的屏幕尺寸和分辨率,确保在各种设备上都能提供良好的用户体验。
事件处理:SliderRange区间组件通常支持多种事件处理机制,如值变化事件、拖动事件等,使得开发者可以根据用户的操作进行相应的处理。
三、使用场景
SliderRange区间组件广泛应用于各种需要用户输入数值范围的应用场景,如:
音乐播放器:用于调节音量大小,通常是一个垂直的SliderRange区间组件。
图片编辑器:用于调节图片的亮度、对比度等参数,通常是一个水平的SliderRange区间组件。
电子商务网站:用于价格筛选,用户可以通过拖动滑块来选择价格范围。
数据可视化:用于调整图表中的数值范围,以便更好地观察数据的变化趋势。
四、组件实现
扩展一个uniapp slider组件diy-sliderrange。支持可视化定义步长、最小值、最大值、区间、激活颜色、按钮颜色等。组件库实现代码如下。
<template>
<view class="slider-range">
<view class="slider-container" :style="{ height: `${containerHeight}px` }">
<view class="slider-track" :style="{
backgroundColor: inactiveColor,
height: `${
barHeight}px`,
top: `${
(Math.max(buttonSize, barHeight) - barHeight) / 2 + 4}px`
}"></view>
<view class="slider-fill" :style="{
backgroundColor: activeColor,
left: `${
leftPercentage}%`,
width: `${
rangePercentage}%`,
height: `${
barHeight}px`,
top: `${
(Math.max(buttonSize, barHeight) - barHeight) / 2 + 4}px`
}"></view>
<view class="slider-handle-container left" :style="{
left: `${
leftPercentage}%`,
top: `${
(Math.max(buttonSize, barHeight) - buttonSize) / 2 + 4}px`
}" @touchstart="startDrag('left')" @touchmove.stop.prevent="drag" @touchend="endDrag">
<view class="slider-handle" :style="{
backgroundColor: buttonColor,
width: `${
buttonSize}px`,
height: `${
buttonSize}px`
}">
<text v-if="valuePosition === 'inside'&&showValue" class="slider-value inside"
:style="{ color: valueColor }">{
{
formatValue(modelValue[0]) }}</text>
</view>
<text v-if="valuePosition === 'below'&&showValue" class="slider-value below"
:style="{ color: valueColor }">{
{
formatValue(modelValue[0]) }}</text>
</view>
<view class="slider-handle-container right" :style="{
left: `${
rightPercentage}%`,
top: `${
(Math.max(buttonSize, barHeight) - buttonSize) / 2 + 4}px`
}" @touchstart="startDrag('right')" @touchmove.stop.prevent="drag" @touchend="endDrag">
<view class="slider-handle" :style="{
backgroundColor: buttonColor,
width: `${
buttonSize}px`,
height: `${
buttonSize}px`
}">
<text v-if="valuePosition === 'inside'&&showValue" class="slider-value inside"
:style="{ color: valueColor }">{
{
formatValue(modelValue[1]) }}</text>
</view>
<text v-if="valuePosition === 'below'&&showValue" class="slider-value below"
:style="{ color: valueColor }">{
{
formatValue(modelValue[1]) }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'diy-sliderrange',
props: {
//区间值
modelValue: {
type: Array,
required: true,
validator: (value) => value.length === 2 && value.every(v => typeof v === 'number')
},
//最小值
min: {
type: Number,
default: 0
},
//最大值
max: {
type: Number,
default: 100
},
//布长
step: {
type: Number,
default: 1
},
//最小区间
minRange: {
type: Number,
default: 0
},
//进度条非激活态颜色
inactiveColor: {
type: String,
default: '#e0e0e0'
},
//进度条激活态颜色
activeColor: {
type: String,
default: '#007aff'
},
//拖动滑块按钮颜色
buttonColor: {
type: String,
default: '#ffffff'
},
//进度条高度
barHeight: {
type: Number,
default: 2
},
//滑块按钮大小
buttonSize: {
type: Number,
default: 32
},
valueColor: {
type: String,
default: '#333333'
},
//是否显示值
showValue: {
type: Boolean,
default: true
},
valuePosition: {
type: String,
default: 'inside',
validator: (value) => ['inside', 'below'].includes(value)
}
},
emits: ['update:modelValue', 'change'],
computed: {
leftPercentage() {
return ((this.modelValue[0] - this.min) / (this.max - this.min)) * 100
},
rightPercentage() {
return ((this.modelValue[1] - this.min) / (this.max - this.min)) * 100
},
rangePercentage() {
return this.rightPercentage - this.leftPercentage
},
containerHeight() {
const baseHeight = Math.max(this.buttonSize, this.barHeight) + 8
return this.valuePosition === 'below' ? baseHeight + 8 : baseHeight
}
},
data() {
return {
isDragging: false,
currentHandle: null,
sliderWidth: 0,
sliderLeft: 0
}
},
mounted() {
this.initSliderDimensions()
},
methods: {
initSliderDimensions() {
const query = uni.createSelectorQuery().in(this)
query.select('.slider-container').boundingClientRect(data => {
if (data) {
this.sliderWidth = data.width
this.sliderLeft = data.left
}
}).exec()
},
startDrag(handle) {
this.isDragging = true
this.currentHandle = handle
},
drag(event) {
if (!this.isDragging) return
const touch = event.touches[0]
const x = touch.clientX - this.sliderLeft
const percentage = Math.max(0, Math.min(100, (x / this.sliderWidth) * 100))
const value = Math.round((percentage / 100) * (this.max - this.min) / this.step) * this.step + this.min
let newValues = [...this.modelValue]
if (this.currentHandle === 'left') {
newValues[0] = Math.min(value, newValues[1] - this.minRange)
newValues[0] = Math.max(this.min, newValues[0])
} else {
newValues[1] = Math.max(value, newValues[0] + this.minRange)
newValues[1] = Math.min(this.max, newValues[1])
}
this.$emit('update:modelValue', newValues)
this.$emit('change', newValues)
},
endDrag() {
this.isDragging = false
this.currentHandle = null
},
formatValue(value) {
return value.toFixed(this.step < 1 ? 1 : 0)
}
}
}
</script>
<style>
.slider-range {
width: 100%;
}
.slider-container {
position: relative;
}
.slider-track {
position: absolute;
width: 100%;
border-radius: 50rpx;
}
.slider-fill {
position: absolute;
}
.slider-handle-container {
position: absolute;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
}
.slider-handle {
border-radius: 50%;
box-shadow:0 0 4px rgba(0, 0, 0, 0.2);
display: flex;
justify-content: center;
align-items: center;
}
.slider-value {
font-size: 12px;
}
.slider-value.below {
margin-top: 4px;
}
</style>
五、组件调用
<template>
<view class="container container329152">
<u-form-item class="diygw-col-24" label="滑块" prop="sliderrange">
<view class="flex1 flex align-center diygw-col-24">
<diy-sliderrange class="flex1" active-color="#07c160" name="sliderrange" v-model="sliderrange" :button-size="32" :min="0" :max="100" :step="1"></diy-sliderrange>
</view>
</u-form-item>
<u-form-item class="diygw-col-24" label="滑块" prop="sliderrange1">
<view class="flex1 flex align-center diygw-col-24">
<diy-sliderrange class="flex1" active-color="#9f05d4" name="sliderrange1" v-model="sliderrange1" :button-size="32" :min="0" :max="100" :step="1"></diy-sliderrange>
</view>
</u-form-item>
<u-form-item class="diygw-col-24" label="滑块" prop="sliderrange2">
<view class="flex1 flex align-center diygw-col-24">
<diy-sliderrange class="flex1" active-color="#fc0c00" name="sliderrange2" v-model="sliderrange2" value-color="#ab0202" :bar-height="7" :button-size="32" :min="0" :max="100" :step="1"></diy-sliderrange>
</view>
</u-form-item>
<u-form-item class="diygw-col-24" label="滑块" prop="sliderrange3">
<view class="flex1 flex align-center diygw-col-24">
<diy-sliderrange class="flex1" active-color="#e60643" name="sliderrange3" v-model="sliderrange3" button-color="#d04c4c" value-color="#ffffff" :bar-height="8" :button-size="33" :min="0" :max="100" :step="1"></diy-sliderrange>
</view>
</u-form-item>
<view class="clearfix"></view>
</view>
</template>
<script>
export default {
data() {
return {
//用户全局信息
userInfo: {
},
//页面传参
globalOption: {
},
//自定义全局变量
globalData: {
isshow: false },
sliderrange: [16, 66],
sliderrange1: [16, 66],
sliderrange2: [16, 66],
sliderrange3: [10, 80]
};
},
onShow() {
this.setCurrentPage(this);
},
onLoad(option) {
this.setCurrentPage(this);
if (option) {
this.setData({
globalOption: this.getOption(option)
});
}
this.init();
},
methods: {
async init() {
}
}
};
</script>
<style lang="scss" scoped>
.container329152 {
}
</style>
六、注意事项
在使用SliderRange区间组件时,需要注意以下几点:
选择合适的步长:步长决定了滑块每次移动的最小单位。选择合适的步长可以使得用户更容易选择到精确的数值范围。
提供清晰的标签和说明:为了确保用户能够正确理解和使用SliderRange区间组件,需要提供清晰的标签和说明来指示数值范围和当前选择的值。
考虑无障碍设计:对于需要支持无障碍访问的应用,需要确保SliderRange区间组件能够与其他辅助技术(如屏幕阅读器)兼容,并提供相应的无障碍支持。
综上所述,SliderRange区间组件是一种功能强大且易于使用的UI元素,适用于多种应用场景。通过合理配置和使用,可以为用户提供良好的交互体验和操作便利性。