You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.8 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 使用普通的js方案实现slider
*/
export default {
watch: {
value(n) {
// 只有在非滑动状态时才可以通过value更新滑块值这里监听是为了让用户触发
if (this.status === 'end') {
this.updateSliderPlacement(n, true)
}
}
},
mounted() {
this.init()
},
methods: {
init() {
this.getSliderRect()
},
// 获取slider尺寸
getSliderRect() {
// 获取滑块条的尺寸信息
setTimeout(() => {
this.$uGetRect('.u-slider').then((rect) => {
this.sliderRect = rect
this.updateSliderPlacement(this.value, true)
})
}, 10)
},
// 是否可以操作
canNotDo() {
return this.disabled
},
// 获取当前手势点的X轴位移值
getTouchX(e) {
return e.touches[0].clientX
},
formatStep(value) {
// 移动点占总长度的百分比
return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step
},
// 发出事件
emitEvent(event, value) {
this.$emit(event, value || this.value)
},
// 标记当前手势的状态
setTouchStatus(status) {
this.status = status
},
onTouchStart(e) {
if (this.canNotDo()) {
return
}
// 标示当前的状态为开始触摸滑动
this.emitEvent('start')
this.setTouchStatus('start')
},
onTouchMove(e) {
if (this.canNotDo()) {
return
}
// 滑块的左边不一定跟屏幕左边接壤,所以需要减去最外层父元素的左边值
const x = this.getTouchX(e)
const { left, width } = this.sliderRect
const distanceX = x - left
// 获得移动距离对整个滑块的百分比值,此为带有多位小数的值,不能用此更新视图
// 否则造成通信阻塞需要每改变一个step值时修改一次视图
const percent = (distanceX / width) * 100
this.setTouchStatus('moving')
this.updateSliderPlacement(percent, true, 'moving')
},
onTouchEnd() {
if (this.canNotDo()) {
return
}
this.emitEvent('end')
this.setTouchStatus('end')
},
// 设置滑点的位置
updateSliderPlacement(value, drag, event) {
// 去掉小数部分同时也是对step步进的处理
const { width } = this.sliderRect
const percent = this.formatStep(value)
// 设置移动的值
const barStyle = {
width: `${percent / 100 * width}px`
}
// 移动期间无需过渡动画
if (drag === true) {
barStyle.transition = 'none'
} else {
// 非移动期间删掉对过渡为空的声明让css中的声明起效
delete barStyle.transition
}
// 修改value值
this.$emit('input', percent)
// 事件的名称
if (event) {
this.emitEvent(event, percent)
}
this.barStyle = barStyle
},
onClick(e) {
if (this.canNotDo()) {
return
}
// 直接点击滑块的情况计算方式与onTouchMove方法相同
const { left, width } = this.sliderRect
const value = ((e.detail.x - left) / width) * 100
this.updateSliderPlacement(value, false, 'click')
}
}
}