|
|
@@ -19,7 +19,7 @@
|
|
|
:y="item.y"
|
|
|
:friction="friction"
|
|
|
:damping="damping"
|
|
|
- :animation="animation"
|
|
|
+ :animation="getItemAnimation(oindex)"
|
|
|
:disabled="isDisabled || props.disabled"
|
|
|
@touchstart="touchStart"
|
|
|
@change="touchMove"
|
|
|
@@ -84,7 +84,10 @@
|
|
|
/** 旧视图下标 */
|
|
|
oldindex: -1,
|
|
|
/** 上次原始下标 */
|
|
|
- lastindex: -1
|
|
|
+ lastindex: -1,
|
|
|
+ /** 当前拖拽坐标(用于小程序 touchend 防回闪) */
|
|
|
+ x: 0,
|
|
|
+ y: 0
|
|
|
})
|
|
|
|
|
|
const ghostEl = reactive({
|
|
|
@@ -222,13 +225,15 @@
|
|
|
active.value = oindex
|
|
|
// 选中项的当前下标
|
|
|
dragEl.index = dragEl.oldindex = target.index
|
|
|
+ dragEl.x = target.x || 0
|
|
|
+ dragEl.y = target.y || 0
|
|
|
ghostEl.x = target.x||0
|
|
|
ghostEl.y = target.y||0
|
|
|
dragEl.content = ghostEl.content = target.content
|
|
|
}
|
|
|
|
|
|
const touchEnd = (e: any) => {
|
|
|
- setTimeout(() => {
|
|
|
+ const finalize = () => {
|
|
|
if(e.target.dataset.remove || active.value==-1) return
|
|
|
setDisabled(e, true)
|
|
|
isDrag.value = false
|
|
|
@@ -246,8 +251,20 @@
|
|
|
isEmit && emitting()
|
|
|
})
|
|
|
})
|
|
|
- },80)
|
|
|
-
|
|
|
+ }
|
|
|
+ // 小程序下 movable-view 在 touchend 会先回到绑定的 x/y,
|
|
|
+ // 先把当前拖拽坐标写回,避免“先回原位”的闪现,同时保留动画
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ const last = cloneList.value[active.value]
|
|
|
+ if (last) {
|
|
|
+ last.x = dragEl.x
|
|
|
+ last.y = dragEl.y
|
|
|
+ }
|
|
|
+ finalize()
|
|
|
+ // #endif
|
|
|
+ // #ifndef MP-WEIXIN
|
|
|
+ setTimeout(finalize, 80)
|
|
|
+ // #endif
|
|
|
}
|
|
|
const emitting = () => {
|
|
|
const clone = [...cloneList.value].sort((a, b) => a.index - b.index)//.map(item => ref(item.content))
|
|
|
@@ -264,6 +281,16 @@
|
|
|
// #endif
|
|
|
if(oindex != active.value) return
|
|
|
const {x, y} = e.detail
|
|
|
+ // 小程序下同步更新绑定坐标,避免 touchend 回弹闪现
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ const activeItem = cloneList.value[active.value]
|
|
|
+ if (activeItem) {
|
|
|
+ activeItem.x = x
|
|
|
+ activeItem.y = y
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+ dragEl.x = x
|
|
|
+ dragEl.y = y
|
|
|
const centerX = x + girdWidth.value / 2
|
|
|
const centerY = y + gridHeight.value / 2
|
|
|
for (let i = 0; i < cloneList.value.length; i++) {
|
|
|
@@ -303,7 +330,9 @@
|
|
|
// 距离
|
|
|
let distance = start - toIndex
|
|
|
// 找到区间所有的项
|
|
|
- while(distance) {
|
|
|
+ let steps = 0
|
|
|
+ const stepLimit = isDrag.value ? 1 : Number.POSITIVE_INFINITY
|
|
|
+ while(distance && steps < stepLimit) {
|
|
|
distance += speed
|
|
|
// 目标
|
|
|
const target = isDrag.value ? (dragEl.index += speed) : (start += speed)
|
|
|
@@ -321,7 +350,7 @@
|
|
|
targetEl.oldindex = targetEl.index
|
|
|
targetEl.index = lastIndex
|
|
|
activeEl.oldindex = activeEl.index //oIndex
|
|
|
- activeEl.index = toIndex
|
|
|
+ activeEl.index = target
|
|
|
// 到达终点,如果是拖拽则不处理
|
|
|
if(!distance && !isDrag.value) {
|
|
|
const rect = gridRects[toIndex]
|
|
|
@@ -333,6 +362,7 @@
|
|
|
emitting()
|
|
|
}
|
|
|
}
|
|
|
+ steps++
|
|
|
}
|
|
|
}
|
|
|
/**
|
|
|
@@ -461,6 +491,12 @@
|
|
|
onUnmounted(clear)
|
|
|
watch(() => props.list, init)
|
|
|
|
|
|
+ const getItemAnimation = (oindex: number) => {
|
|
|
+ // 拖拽中的项不做动画,避免小程序抖动
|
|
|
+ if (isDrag.value && oindex === active.value) return false
|
|
|
+ return animation.value
|
|
|
+ }
|
|
|
+
|
|
|
// #ifdef VUE3
|
|
|
expose({
|
|
|
remove,
|
|
|
@@ -469,7 +505,8 @@
|
|
|
push,
|
|
|
unshift,
|
|
|
shift,
|
|
|
- pop
|
|
|
+ pop,
|
|
|
+ refresh: getRect
|
|
|
})
|
|
|
// #endif
|
|
|
return {
|
|
|
@@ -489,6 +526,7 @@
|
|
|
|
|
|
active,
|
|
|
animation,
|
|
|
+ getItemAnimation,
|
|
|
|
|
|
afterEl,
|
|
|
ghostEl,
|