fix: 修复手机端图片等比例缩小和拖拽按钮触摸支持

- 移除 .comparison-image img 的 min-width 和 min-height,修复手机端图片无法等比例缩小的问题
- 为拖拽分割线添加触摸事件支持(touchstart/touchmove/touchend),使手机端可以正常拖拽对比视图
This commit is contained in:
jingrow 2026-01-04 22:41:47 +08:00
parent ee2f59df81
commit c489d41941
2 changed files with 41 additions and 20 deletions

View File

@ -780,27 +780,38 @@ const adjustContainerSize = async () => {
watch([uploadedImageUrl, resultImageUrl], adjustContainerSize, { immediate: true })
const handleSplitLineMouseDown = (e: MouseEvent) => {
const handleSplitLineMouseDown = (e: MouseEvent | TouchEvent) => {
e.preventDefault()
isDraggingSplitLine.value = true
const handleMouseMove = (moveEvent: MouseEvent) => {
const getClientX = (event: MouseEvent | TouchEvent): number => {
if ('touches' in event && event.touches.length > 0) {
return event.touches[0].clientX
}
return (event as MouseEvent).clientX
}
const handleMove = (moveEvent: MouseEvent | TouchEvent) => {
if (!comparisonContainerRef.value || !isDraggingSplitLine.value) return
const rect = comparisonContainerRef.value.getBoundingClientRect()
const x = moveEvent.clientX - rect.left
const x = getClientX(moveEvent) - rect.left
const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100))
splitPosition.value = percentage
}
const handleMouseUp = () => {
const handleEnd = () => {
isDraggingSplitLine.value = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
document.removeEventListener('mousemove', handleMove as EventListener)
document.removeEventListener('mouseup', handleEnd)
document.removeEventListener('touchmove', handleMove as EventListener)
document.removeEventListener('touchend', handleEnd)
}
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('mousemove', handleMove as EventListener)
document.addEventListener('mouseup', handleEnd)
document.addEventListener('touchmove', handleMove as EventListener, { passive: false })
document.addEventListener('touchend', handleEnd)
}
const handlePaste = async (event: ClipboardEvent) => {
@ -1088,7 +1099,7 @@ onUnmounted(() => {
<div class="comparison-image result-image" :style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }">
<img ref="resultImageRef" :src="resultImageUrl" :alt="t('Background Removed')" @load="adjustContainerSize" />
</div>
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown">
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown" @touchstart.prevent.stop="handleSplitLineMouseDown">
<div class="split-line-handle">
<i class="fa fa-arrows-h"></i>
</div>
@ -1355,7 +1366,7 @@ onUnmounted(() => {
<div class="comparison-image result-image" :style="{ clipPath: `inset(0 0 0 ${splitPosition}%)` }">
<img ref="resultImageRef" :src="resultImageUrl" :alt="t('Background Removed')" @load="adjustContainerSize" />
</div>
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown">
<div class="split-line" :class="{ dragging: isDraggingSplitLine }" :style="{ left: `${splitPosition}%` }" @mousedown.prevent.stop="handleSplitLineMouseDown" @touchstart.prevent.stop="handleSplitLineMouseDown">
<div class="split-line-handle">
<i class="fa fa-arrows-h"></i>
</div>
@ -2331,8 +2342,6 @@ onUnmounted(() => {
img {
display: block;
min-width: 620px;
min-height: 620px;
max-width: 100%;
max-height: 100%;
width: auto;

View File

@ -117,6 +117,7 @@
:class="{ 'dragging': isDraggingSplitLine }"
:style="{ left: `${splitPosition}%` }"
@mousedown.prevent.stop="handleSplitLineMouseDown"
@touchstart.prevent.stop="handleSplitLineMouseDown"
>
<div class="split-line-handle">
<i class="fa fa-arrows-h"></i>
@ -568,27 +569,38 @@ const getHistoryThumbnailUrl = (item: HistoryItem): string => {
return item.originalImageUrl
}
const handleSplitLineMouseDown = (e: MouseEvent) => {
const handleSplitLineMouseDown = (e: MouseEvent | TouchEvent) => {
e.preventDefault()
isDraggingSplitLine.value = true
const handleMouseMove = (moveEvent: MouseEvent) => {
const getClientX = (event: MouseEvent | TouchEvent): number => {
if ('touches' in event && event.touches.length > 0) {
return event.touches[0].clientX
}
return (event as MouseEvent).clientX
}
const handleMove = (moveEvent: MouseEvent | TouchEvent) => {
if (!comparisonContainerRef.value || !isDraggingSplitLine.value) return
const rect = comparisonContainerRef.value.getBoundingClientRect()
const x = moveEvent.clientX - rect.left
const x = getClientX(moveEvent) - rect.left
const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100))
splitPosition.value = percentage
}
const handleMouseUp = () => {
const handleEnd = () => {
isDraggingSplitLine.value = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
document.removeEventListener('mousemove', handleMove as EventListener)
document.removeEventListener('mouseup', handleEnd)
document.removeEventListener('touchmove', handleMove as EventListener)
document.removeEventListener('touchend', handleEnd)
}
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('mousemove', handleMove as EventListener)
document.addEventListener('mouseup', handleEnd)
document.addEventListener('touchmove', handleMove as EventListener, { passive: false })
document.addEventListener('touchend', handleEnd)
}
const handleRemoveBackground = async () => {