You've already forked SmartisanNote.Remake
future #10
@@ -606,7 +606,9 @@ const dragState = ref({
|
||||
currentY: 0,
|
||||
longPressTimer: null,
|
||||
isLongPress: false,
|
||||
indicator: null
|
||||
indicator: null,
|
||||
lastCheckTime: 0,
|
||||
lastMoveTime: 0
|
||||
})
|
||||
|
||||
// 插入图片
|
||||
@@ -814,7 +816,7 @@ const handleTouchStart = (e) => {
|
||||
dragState.value.startX = e.touches[0].clientX
|
||||
dragState.value.startY = e.touches[0].clientY
|
||||
|
||||
// 设置长按检测定时器(400毫秒)
|
||||
// 设置长按检测定时器(300毫秒)
|
||||
dragState.value.longPressTimer = setTimeout(() => {
|
||||
dragState.value.isLongPress = true
|
||||
dragState.value.draggedImage = img
|
||||
@@ -823,10 +825,10 @@ const handleTouchStart = (e) => {
|
||||
|
||||
// 添加拖拽样式
|
||||
img.classList.add('dragging')
|
||||
img.style.opacity = '0.85'
|
||||
img.style.transform = 'scale(0.99)'
|
||||
img.style.opacity = '0.9'
|
||||
img.style.transform = 'scale(0.98)'
|
||||
img.style.zIndex = '999'
|
||||
img.style.transition = 'all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img.style.transition = 'all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
|
||||
// 添加拖拽指示器
|
||||
const indicator = document.createElement('div')
|
||||
@@ -836,32 +838,33 @@ const handleTouchStart = (e) => {
|
||||
indicator.style.left = '50%'
|
||||
indicator.style.transform = 'translate(-50%, -50%)'
|
||||
indicator.style.padding = '8px 16px'
|
||||
indicator.style.background = 'rgba(0, 0, 0, 0.75)'
|
||||
indicator.style.background = 'rgba(0, 0, 0, 0.8)'
|
||||
indicator.style.color = 'white'
|
||||
indicator.style.borderRadius = '16px'
|
||||
indicator.style.fontSize = '13px'
|
||||
indicator.style.fontSize = '14px'
|
||||
indicator.style.fontWeight = '500'
|
||||
indicator.style.zIndex = '1000'
|
||||
indicator.style.opacity = '0'
|
||||
indicator.style.transition = 'opacity 0.2s ease'
|
||||
indicator.style.transition = 'opacity 0.15s ease-out'
|
||||
indicator.textContent = '拖拽排序'
|
||||
document.body.appendChild(indicator)
|
||||
|
||||
// 渐显指示器
|
||||
setTimeout(() => {
|
||||
indicator.style.opacity = '1'
|
||||
}, 10)
|
||||
}, 5)
|
||||
|
||||
// 保存指示器引用以便后续移除
|
||||
dragState.value.indicator = indicator
|
||||
|
||||
// 添加震动反馈(如果设备支持)
|
||||
if (navigator.vibrate) {
|
||||
navigator.vibrate(15)
|
||||
navigator.vibrate(10)
|
||||
}
|
||||
|
||||
// 阻止页面滚动
|
||||
e.preventDefault()
|
||||
}, 400) // 400毫秒长按触发拖拽
|
||||
}, 300) // 300毫秒长按触发拖拽
|
||||
}
|
||||
|
||||
// 处理触摸移动事件
|
||||
@@ -901,14 +904,20 @@ const handleTouchMove = (e) => {
|
||||
const deltaY = dragState.value.currentY - dragState.value.startY
|
||||
|
||||
// 更新图片位置,添加缓动效果
|
||||
const easeFactor = 0.7
|
||||
img.style.transform = `translateY(${deltaY * easeFactor}px) scale(0.99)`
|
||||
const easeFactor = 0.9 // 调整缓动因子使拖拽更跟手
|
||||
img.style.transform = `translateY(${deltaY * easeFactor}px) scale(0.98)`
|
||||
|
||||
// 使用requestAnimationFrame优化性能
|
||||
requestAnimationFrame(() => {
|
||||
// 检查与其他图片的碰撞,实现排序
|
||||
// 使用节流优化,避免过于频繁的检查
|
||||
if (!dragState.value.lastMoveTime) {
|
||||
dragState.value.lastMoveTime = 0
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
// 限制检查频率为每25ms一次,提高响应速度
|
||||
if (now - dragState.value.lastMoveTime >= 25) {
|
||||
dragState.value.lastMoveTime = now
|
||||
checkAndSwapImages(img, deltaY)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 处理触摸结束事件
|
||||
@@ -928,24 +937,25 @@ const handleTouchEnd = (e) => {
|
||||
const img = dragState.value.draggedImage
|
||||
|
||||
// 添加释放动画
|
||||
img.style.transition = 'all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img.style.transition = 'all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img.style.transform = 'translateY(0) scale(1)'
|
||||
img.style.opacity = '1'
|
||||
|
||||
// 移除拖拽指示器
|
||||
if (dragState.value.indicator) {
|
||||
const indicator = dragState.value.indicator
|
||||
indicator.style.transition = 'opacity 0.15s ease-out'
|
||||
indicator.style.opacity = '0'
|
||||
setTimeout(() => {
|
||||
if (indicator.parentNode) {
|
||||
indicator.parentNode.removeChild(indicator)
|
||||
}
|
||||
}, 250)
|
||||
}, 150)
|
||||
}
|
||||
|
||||
// 添加震动反馈(如果设备支持)
|
||||
if (navigator.vibrate) {
|
||||
navigator.vibrate(8)
|
||||
navigator.vibrate(5)
|
||||
}
|
||||
|
||||
// 延迟重置样式以显示动画
|
||||
@@ -955,7 +965,7 @@ const handleTouchEnd = (e) => {
|
||||
img.style.zIndex = ''
|
||||
img.style.transition = ''
|
||||
}
|
||||
}, 250)
|
||||
}, 200)
|
||||
|
||||
// 重置状态
|
||||
dragState.value.isLongPress = false
|
||||
@@ -985,19 +995,20 @@ const handleTouchCancel = (e) => {
|
||||
const img = dragState.value.draggedImage
|
||||
|
||||
// 添加取消动画
|
||||
img.style.transition = 'all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img.style.transition = 'all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img.style.transform = 'translateY(0) scale(1)'
|
||||
img.style.opacity = '1'
|
||||
|
||||
// 移除拖拽指示器
|
||||
if (dragState.value.indicator) {
|
||||
const indicator = dragState.value.indicator
|
||||
indicator.style.transition = 'opacity 0.15s ease-out'
|
||||
indicator.style.opacity = '0'
|
||||
setTimeout(() => {
|
||||
if (indicator.parentNode) {
|
||||
indicator.parentNode.removeChild(indicator)
|
||||
}
|
||||
}, 250)
|
||||
}, 150)
|
||||
}
|
||||
|
||||
// 延迟重置样式以显示动画
|
||||
@@ -1007,7 +1018,7 @@ const handleTouchCancel = (e) => {
|
||||
img.style.zIndex = ''
|
||||
img.style.transition = ''
|
||||
}
|
||||
}, 250)
|
||||
}, 200)
|
||||
|
||||
// 重置状态
|
||||
dragState.value.isLongPress = false
|
||||
@@ -1026,7 +1037,7 @@ const checkAndSwapImages = (draggedImg, deltaY) => {
|
||||
|
||||
// 计算拖拽图片的中心位置
|
||||
const draggedRect = draggedImg.getBoundingClientRect()
|
||||
const draggedCenterY = draggedRect.top + draggedRect.height / 2 + deltaY * 0.8 // 添加缓动因子
|
||||
const draggedCenterY = draggedRect.top + draggedRect.height / 2 + deltaY * 0.9 // 调整缓动因子以匹配触摸移动
|
||||
|
||||
// 查找最近的图片进行交换
|
||||
for (let i = 0; i < allImages.length; i++) {
|
||||
@@ -1037,23 +1048,11 @@ const checkAndSwapImages = (draggedImg, deltaY) => {
|
||||
const targetCenterY = targetRect.top + targetRect.height / 2
|
||||
|
||||
// 检查是否与目标图片重叠,使用更精确的碰撞检测
|
||||
const overlapThreshold = (draggedRect.height + targetRect.height) * 0.4
|
||||
const overlapThreshold = (draggedRect.height + targetRect.height) * 0.4 // 调整阈值使交换更灵敏
|
||||
const distance = Math.abs(draggedCenterY - targetCenterY)
|
||||
|
||||
if (distance < overlapThreshold) {
|
||||
// 添加接近效果
|
||||
targetImg.style.transition = 'all 0.2s ease'
|
||||
targetImg.style.transform = 'scale(1.02)'
|
||||
targetImg.style.boxShadow = '0 0 0 2px var(--primary)'
|
||||
|
||||
// 短暂延迟后恢复
|
||||
setTimeout(() => {
|
||||
targetImg.style.transform = ''
|
||||
targetImg.style.boxShadow = ''
|
||||
targetImg.style.transition = ''
|
||||
}, 200)
|
||||
|
||||
// 交换位置
|
||||
// 直接交换位置,移除视觉反馈以避免闪烁
|
||||
swapImages(draggedImg, targetImg)
|
||||
break
|
||||
}
|
||||
@@ -1067,42 +1066,12 @@ const swapImages = (img1, img2) => {
|
||||
|
||||
// 如果两张图片在同一父元素中
|
||||
if (parent1 === parent2) {
|
||||
// 添加交换动画
|
||||
img1.style.transition = 'transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
img2.style.transition = 'transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94)'
|
||||
|
||||
// 获取当前位置
|
||||
const rect1 = img1.getBoundingClientRect()
|
||||
const rect2 = img2.getBoundingClientRect()
|
||||
|
||||
// 计算位移
|
||||
const translateY1 = rect2.top - rect1.top
|
||||
const translateY2 = rect1.top - rect2.top
|
||||
|
||||
// 应用位移
|
||||
img1.style.transform = `translateY(${translateY1}px) scale(0.99)`
|
||||
img2.style.transform = `translateY(${translateY2}px) scale(0.99)`
|
||||
|
||||
// 交换DOM位置
|
||||
// 直接交换DOM位置,避免复杂的动画导致的闪烁
|
||||
const tempMarker = document.createElement('div')
|
||||
parent1.insertBefore(tempMarker, img1)
|
||||
parent1.insertBefore(img1, img2)
|
||||
parent1.insertBefore(img2, tempMarker)
|
||||
tempMarker.remove()
|
||||
|
||||
// 重置变换
|
||||
setTimeout(() => {
|
||||
img1.style.transform = 'scale(0.99)'
|
||||
img2.style.transform = 'scale(0.99)'
|
||||
|
||||
// 短暂延时后移除过渡效果
|
||||
setTimeout(() => {
|
||||
img1.style.transition = ''
|
||||
img2.style.transition = ''
|
||||
img1.style.transform = ''
|
||||
img2.style.transform = ''
|
||||
}, 250)
|
||||
}, 250)
|
||||
} else {
|
||||
// 不同父元素的情况(更复杂,需要特殊处理)
|
||||
// 这里简化处理,实际项目中可能需要更复杂的逻辑
|
||||
@@ -1680,13 +1649,12 @@ defineExpose({
|
||||
}
|
||||
|
||||
:deep(.editor-content .editor-image.dragging) {
|
||||
opacity: 0.85;
|
||||
transform: scale(0.99);
|
||||
opacity: 0.9;
|
||||
transform: scale(0.98);
|
||||
z-index: 999;
|
||||
transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
transition: transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.15s ease; /* 优化过渡效果 */
|
||||
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.22);
|
||||
will-change: transform;
|
||||
filter: brightness(1.03);
|
||||
will-change: transform, opacity; /* 提示浏览器优化这些属性 */
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
|
||||
Reference in New Issue
Block a user