|
@@ -34,11 +34,12 @@
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 第二个滑块 -->
|
|
<!-- 第二个滑块 -->
|
|
|
- <view class="block-item" v-if="secondBlock.show" :style="{
|
|
|
|
|
- left: getSecondBlockPosition,
|
|
|
|
|
- zIndex: secondBlock.zIndex
|
|
|
|
|
- }" data-sort="secondBlock" @touchstart.stop.prevent="onTouchStart" @touchmove.stop.prevent="onTouchMove"
|
|
|
|
|
- @touchend.stop.prevent="onTouchEnd">
|
|
|
|
|
|
|
+ <view class="block-item" v-if="secondBlock.show" :style="{
|
|
|
|
|
+ left: getSecondBlockPosition,
|
|
|
|
|
+ zIndex: secondBlock.zIndex
|
|
|
|
|
+ }" data-sort="secondBlock" @touchstart.stop.prevent="onTouchStart" @touchmove.stop.prevent="onTouchMove"
|
|
|
|
|
+ @touchend.stop.prevent="onTouchEnd" @mousedown.stop="onTouchStart" @mousemove.stop="onTouchMove"
|
|
|
|
|
+ @mouseleave.stop="onTouchEnd" @mouseup.stop="onTouchEnd">
|
|
|
|
|
|
|
|
<!-- 非微信小程序插槽 -->
|
|
<!-- 非微信小程序插槽 -->
|
|
|
<!-- #ifndef MP-WEIXIN -->
|
|
<!-- #ifndef MP-WEIXIN -->
|
|
@@ -181,8 +182,10 @@
|
|
|
show: true,
|
|
show: true,
|
|
|
zIndex: 2,
|
|
zIndex: 2,
|
|
|
},
|
|
},
|
|
|
- // 滑动中
|
|
|
|
|
|
|
+ // 拖动中
|
|
|
dragging: '',
|
|
dragging: '',
|
|
|
|
|
+ // H5 端拖动锁,防止 mouseup/mouseleave 重复触发 end,以及松手后再次移入时还在滑动
|
|
|
|
|
+ isDragging: false,
|
|
|
// 刻度线设置
|
|
// 刻度线设置
|
|
|
scaleInfo: {
|
|
scaleInfo: {
|
|
|
show: true,
|
|
show: true,
|
|
@@ -294,7 +297,10 @@
|
|
|
* @param {Event} e 触摸事件对象
|
|
* @param {Event} e 触摸事件对象
|
|
|
*/
|
|
*/
|
|
|
onTouchStart(e) {
|
|
onTouchStart(e) {
|
|
|
|
|
+ // 如果上一次拖动未结束,不响应新的 mousedown(避免 H5 端 mouseup 之后又 mousedown 混乱)
|
|
|
|
|
+ if (this.isDragging) return
|
|
|
if (this.disabled) return
|
|
if (this.disabled) return
|
|
|
|
|
+ this.isDragging = true
|
|
|
// 设置当前拖动的滑块
|
|
// 设置当前拖动的滑块
|
|
|
this.dragging = e.currentTarget.dataset.sort
|
|
this.dragging = e.currentTarget.dataset.sort
|
|
|
// 调整z-index,确保当前拖动的滑块在上方
|
|
// 调整z-index,确保当前拖动的滑块在上方
|
|
@@ -302,7 +308,7 @@
|
|
|
this.firstBlock.zIndex = this.secondBlock.zIndex + 1 :
|
|
this.firstBlock.zIndex = this.secondBlock.zIndex + 1 :
|
|
|
this.secondBlock.zIndex = this.firstBlock.zIndex + 1
|
|
this.secondBlock.zIndex = this.firstBlock.zIndex + 1
|
|
|
// 记录开始位置和初始值
|
|
// 记录开始位置和初始值
|
|
|
- this.startDragPostion = e.changedTouches ? e.changedTouches[0].pageX : e.pageX
|
|
|
|
|
|
|
+ this.startDragPostion = (e.changedTouches && e.changedTouches[0]) ? e.changedTouches[0].pageX : (e.pageX || 0)
|
|
|
this.startValue = e.currentTarget.dataset.sort == 'firstBlock' ? this.firstValue : this.secondValue
|
|
this.startValue = e.currentTarget.dataset.sort == 'firstBlock' ? this.firstValue : this.secondValue
|
|
|
// 触发开始事件
|
|
// 触发开始事件
|
|
|
this.$emit('start', {
|
|
this.$emit('start', {
|
|
@@ -319,6 +325,8 @@
|
|
|
*/
|
|
*/
|
|
|
onTouchMove(e) {
|
|
onTouchMove(e) {
|
|
|
if (this.disabled) return
|
|
if (this.disabled) return
|
|
|
|
|
+ // 拖动已结束(mouseup/mouseleave 后又移入),直接拦截
|
|
|
|
|
+ if (!this.isDragging) return
|
|
|
this.onDrag(e)
|
|
this.onDrag(e)
|
|
|
},
|
|
},
|
|
|
|
|
|
|
@@ -327,6 +335,9 @@
|
|
|
* @param {Event} e 触摸事件对象
|
|
* @param {Event} e 触摸事件对象
|
|
|
*/
|
|
*/
|
|
|
onTouchEnd(e) {
|
|
onTouchEnd(e) {
|
|
|
|
|
+ // 拖动已结束过(mouseup 和 mouseleave 都会触发),避免重复发 end
|
|
|
|
|
+ if (!this.isDragging) return
|
|
|
|
|
+ this.isDragging = false
|
|
|
this.dragging = ''
|
|
this.dragging = ''
|
|
|
if (this.disabled) return
|
|
if (this.disabled) return
|
|
|
this.onDrag(e, true)
|
|
this.onDrag(e, true)
|
|
@@ -338,13 +349,47 @@
|
|
|
* @param {boolean} end 是否结束拖动
|
|
* @param {boolean} end 是否结束拖动
|
|
|
*/
|
|
*/
|
|
|
onDrag(e, end = false) {
|
|
onDrag(e, end = false) {
|
|
|
- let pageX = e.changedTouches ? e.changedTouches[0].pageX : e.pageX
|
|
|
|
|
|
|
+ // 兼容 MouseEvent、TouchEvent、以及 e 为 null 的情况
|
|
|
|
|
+ let pageX = 0
|
|
|
|
|
+ if (e && e.changedTouches && e.changedTouches[0]) {
|
|
|
|
|
+ pageX = e.changedTouches[0].pageX
|
|
|
|
|
+ } else if (e && typeof e.pageX === 'number') {
|
|
|
|
|
+ pageX = e.pageX
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果 end 时无法拿到 pageX,使用最后记录的 startDragPostion(也就是不移动,只确认 end)
|
|
|
|
|
+ if (end && pageX === 0 && this.startDragPostion) {
|
|
|
|
|
+ pageX = this.startDragPostion
|
|
|
|
|
+ }
|
|
|
|
|
+ // 兜底 e.currentTarget,取当前正在拖动的滑块
|
|
|
|
|
+ let sort = (e && e.currentTarget && e.currentTarget.dataset && e.currentTarget.dataset.sort) || this.dragging
|
|
|
let view = uni.createSelectorQuery().in(this).select('.block-bar')
|
|
let view = uni.createSelectorQuery().in(this).select('.block-bar')
|
|
|
view.boundingClientRect(data => {
|
|
view.boundingClientRect(data => {
|
|
|
|
|
+ // DOM 还没渲染好时 data 可能为 null,做兜底
|
|
|
|
|
+ if (!data || !data.width) {
|
|
|
|
|
+ if (end) {
|
|
|
|
|
+ this.$emit('end', {
|
|
|
|
|
+ block: sort,
|
|
|
|
|
+ value: this.startValue,
|
|
|
|
|
+ values: [Math.min(this.firstValue, this.secondValue), Math.max(this.firstValue, this.secondValue)]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
// 计算拖动距离对应的数值变化
|
|
// 计算拖动距离对应的数值变化
|
|
|
let diff = ((pageX - this.startDragPostion) / data.width) * (this.max - this.min)
|
|
let diff = ((pageX - this.startDragPostion) / data.width) * (this.max - this.min)
|
|
|
|
|
+ // 如果 diff 是 NaN,跳过这次更新
|
|
|
|
|
+ if (isNaN(diff)) {
|
|
|
|
|
+ if (end) {
|
|
|
|
|
+ this.$emit('end', {
|
|
|
|
|
+ block: sort,
|
|
|
|
|
+ value: this.startValue,
|
|
|
|
|
+ values: [Math.min(this.firstValue, this.secondValue), Math.max(this.firstValue, this.secondValue)]
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
// 更新值
|
|
// 更新值
|
|
|
- this.onUpdateValue(this.startValue + diff, e.currentTarget.dataset.sort, end)
|
|
|
|
|
|
|
+ this.onUpdateValue(this.startValue + diff, sort, end)
|
|
|
}).exec()
|
|
}).exec()
|
|
|
},
|
|
},
|
|
|
|
|
|
|
@@ -355,6 +400,11 @@
|
|
|
* @param {boolean} end 是否结束拖动
|
|
* @param {boolean} end 是否结束拖动
|
|
|
*/
|
|
*/
|
|
|
onUpdateValue(value, sort, end = false) {
|
|
onUpdateValue(value, sort, end = false) {
|
|
|
|
|
+ // 入口 NaN 防护:如果 value 是 NaN,降级为当前滑块已有值
|
|
|
|
|
+ if (isNaN(value)) {
|
|
|
|
|
+ value = sort == 'firstBlock' ? this.firstValue : this.secondValue
|
|
|
|
|
+ if (isNaN(value)) value = this.min
|
|
|
|
|
+ }
|
|
|
// 限制值在范围内
|
|
// 限制值在范围内
|
|
|
if (value < this.min) value = this.min
|
|
if (value < this.min) value = this.min
|
|
|
if (value > this.max) value = this.max
|
|
if (value > this.max) value = this.max
|