|
|
@@ -94,6 +94,19 @@ export class CanvasPhotoEditor {
|
|
|
this.history = []
|
|
|
this.isHistory = false
|
|
|
this.currentIndex = -1; // 当前在第几步
|
|
|
+ // 新增:触摸状态
|
|
|
+ this.touchState = {
|
|
|
+ isTouching: false, // 是否触摸中
|
|
|
+ isPinching: false, // 是否双指缩放中
|
|
|
+ startDistance: 0, // 双指初始距离
|
|
|
+ startScale: 0, // 缩放初始值
|
|
|
+ startX: 0, // 单指初始X
|
|
|
+ startY: 0, // 单指初始Y
|
|
|
+ lastTouchOffsetX: 0, // 触摸初始偏移X
|
|
|
+ lastTouchOffsetY: 0, // 触摸初始偏移Y
|
|
|
+ touchStartTime: 0 // 触摸开始时间(防点击穿透)
|
|
|
+ }
|
|
|
+
|
|
|
// 绑定事件
|
|
|
this.handleMouseDown = this.handleMouseDown.bind(this)
|
|
|
this.handleMouseMove = this.handleMouseMove.bind(this)
|
|
|
@@ -158,7 +171,12 @@ export class CanvasPhotoEditor {
|
|
|
document.addEventListener('mousemove', this.handleMouseMove)//移动鼠标时触发
|
|
|
document.addEventListener('mouseup', this.handleMouseUp)//释放鼠标按键时触发
|
|
|
document.addEventListener('mouseleave', this.handleMouseLeave)//离开触发
|
|
|
-
|
|
|
+
|
|
|
+ // 新增:移动端触摸事件
|
|
|
+ this.canvas.addEventListener('touchstart', this.handleTouchStart.bind(this), { passive: false })
|
|
|
+ this.canvas.addEventListener('touchmove', this.handleTouchMove.bind(this), { passive: false })
|
|
|
+ this.canvas.addEventListener('touchend', this.handleTouchEnd.bind(this))
|
|
|
+ this.canvas.addEventListener('touchcancel', this.handleTouchEnd.bind(this))
|
|
|
// 初始化画布
|
|
|
this.resizeCanvas()
|
|
|
this.resetPosition()
|
|
|
@@ -182,6 +200,11 @@ export class CanvasPhotoEditor {
|
|
|
document.removeEventListener('mousemove', this.handleMouseMove)//移动鼠标时触发
|
|
|
document.removeEventListener('mouseup', this.handleMouseUp)//释放鼠标按键时触发
|
|
|
document.removeEventListener('mouseleave', this.handleMouseLeave)//离开触发
|
|
|
+ // 新增:解绑触摸事件
|
|
|
+ this.canvas.removeEventListener('touchstart', this.handleTouchStart)
|
|
|
+ this.canvas.removeEventListener('touchmove', this.handleTouchMove)
|
|
|
+ this.canvas.removeEventListener('touchend', this.handleTouchEnd)
|
|
|
+ this.canvas.removeEventListener('touchcancel', this.handleTouchEnd)
|
|
|
this.imgCache.clear()
|
|
|
}
|
|
|
|
|
|
@@ -536,6 +559,131 @@ export class CanvasPhotoEditor {
|
|
|
this.drawAllPages()
|
|
|
console.log('tempArrow', this.indexing, this.tempArrow)
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算双指之间的距离
|
|
|
+ * @param {TouchList} touches - 触摸点列表
|
|
|
+ * @returns {number} 双指距离
|
|
|
+ */
|
|
|
+getTouchDistance(touches) {
|
|
|
+ if (touches.length < 2) return 0
|
|
|
+ const touch1 = touches[0]
|
|
|
+ const touch2 = touches[1]
|
|
|
+ const dx = touch2.clientX - touch1.clientX
|
|
|
+ const dy = touch2.clientY - touch1.clientY
|
|
|
+ return Math.sqrt(dx * dx + dy * dy)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 计算双指中点坐标
|
|
|
+ * @param {TouchList} touches - 触摸点列表
|
|
|
+ * @returns {Object} 中点坐标 {x, y}
|
|
|
+ */
|
|
|
+getTouchCenter(touches) {
|
|
|
+ if (touches.length < 2) return { x: 0, y: 0 }
|
|
|
+ const touch1 = touches[0]
|
|
|
+ const touch2 = touches[1]
|
|
|
+ return {
|
|
|
+ x: (touch1.clientX + touch2.clientX) / 2,
|
|
|
+ y: (touch1.clientY + touch2.clientY) / 2
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 触摸开始事件
|
|
|
+ * @param {TouchEvent} e - 触摸事件
|
|
|
+ */
|
|
|
+handleTouchStart(e) {
|
|
|
+ e.preventDefault() // 阻止默认滚动行为
|
|
|
+ const rect = this.canvas.getBoundingClientRect()
|
|
|
+ this.touchState.isTouching = true
|
|
|
+ this.touchState.touchStartTime = Date.now()
|
|
|
+
|
|
|
+ // 双指缩放开始
|
|
|
+ if (e.touches.length === 2) {
|
|
|
+ this.touchState.isPinching = true
|
|
|
+ this.touchState.startDistance = this.getTouchDistance(e.touches)
|
|
|
+ this.touchState.startScale = this._scale // 记录初始缩放值
|
|
|
+
|
|
|
+ // 计算双指中点作为缩放中心
|
|
|
+ const center = this.getTouchCenter(e.touches)
|
|
|
+ this.touchState.lastTouchOffsetX = this.drawOffsetX
|
|
|
+ this.touchState.lastTouchOffsetY = this.drawOffsetY
|
|
|
+ this.touchState.scaleCenterX = center.x - rect.left
|
|
|
+ this.touchState.scaleCenterY = center.y - rect.top
|
|
|
+ }
|
|
|
+ // 单指拖拽开始
|
|
|
+ else if (e.touches.length === 1) {
|
|
|
+ const touch = e.touches[0]
|
|
|
+ this.touchState.startX = touch.clientX
|
|
|
+ this.touchState.startY = touch.clientY
|
|
|
+ this.touchState.lastTouchOffsetX = this.drawOffsetX
|
|
|
+ this.touchState.lastTouchOffsetY = this.drawOffsetY
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 触摸移动事件
|
|
|
+ * @param {TouchEvent} e - 触摸事件
|
|
|
+ */
|
|
|
+handleTouchMove(e) {
|
|
|
+ if (!this.touchState.isTouching) return
|
|
|
+ e.preventDefault()
|
|
|
+ const rect = this.canvas.getBoundingClientRect()
|
|
|
+
|
|
|
+ // 双指缩放逻辑
|
|
|
+ if (e.touches.length === 2 && this.touchState.isPinching) {
|
|
|
+ const currentDistance = this.getTouchDistance(e.touches)
|
|
|
+ const scaleRatio = currentDistance / this.touchState.startDistance
|
|
|
+ const newScale = Math.max(this._scaleMin, Math.min(this._scaleMax, this.touchState.startScale * scaleRatio))
|
|
|
+
|
|
|
+ // 计算缩放偏移(保证缩放中心在双指中点)
|
|
|
+ const scaleDiff = newScale / this._scale
|
|
|
+ this.drawOffsetX = (this.touchState.scaleCenterX - (this.touchState.scaleCenterX - this.touchState.lastTouchOffsetX) * scaleDiff)
|
|
|
+ this.drawOffsetY = (this.touchState.scaleCenterY - (this.touchState.scaleCenterY - this.touchState.lastTouchOffsetY) * scaleDiff)
|
|
|
+
|
|
|
+ this.scale = newScale // 触发重绘
|
|
|
+ }
|
|
|
+ // 单指拖拽逻辑
|
|
|
+ else if (e.touches.length === 1 && !this.touchState.isPinching) {
|
|
|
+ const touch = e.touches[0]
|
|
|
+ const deltaX = touch.clientX - this.touchState.startX
|
|
|
+ const deltaY = touch.clientY - this.touchState.startY
|
|
|
+
|
|
|
+ // 更新拖拽偏移(和鼠标拖拽逻辑一致)
|
|
|
+ this.drawOffsetX = this.touchState.lastTouchOffsetX + deltaX
|
|
|
+ this.drawOffsetY = this.touchState.lastTouchOffsetY + deltaY
|
|
|
+
|
|
|
+ // 实时重绘(保持拖拽流畅)
|
|
|
+ this.drawAllPages()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 触摸结束事件
|
|
|
+ * @param {TouchEvent} e - 触摸事件
|
|
|
+ */
|
|
|
+handleTouchEnd(e) {
|
|
|
+ // 过滤快速点击(防止点击穿透)
|
|
|
+ const touchDuration = Date.now() - this.touchState.touchStartTime
|
|
|
+ if (touchDuration < 300 && e.touches.length === 0) {
|
|
|
+ // 模拟点击事件(可选:需要点击逻辑的话)
|
|
|
+ const touch = e.changedTouches[0]
|
|
|
+ const clickEvent = new MouseEvent('mousedown', {
|
|
|
+ clientX: touch.clientX,
|
|
|
+ clientY: touch.clientY,
|
|
|
+ button: 0
|
|
|
+ })
|
|
|
+ this.canvas.dispatchEvent(clickEvent)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置触摸状态
|
|
|
+ this.touchState.isTouching = false
|
|
|
+ this.touchState.isPinching = false
|
|
|
+ this.touchState.startDistance = 0
|
|
|
+ this.touchState.startScale = 0
|
|
|
+}
|
|
|
+
|
|
|
// --- 拖拽预览:轻量级绘制,仅更新偏移(替代全量重绘)---
|
|
|
drawDragPreview() {
|
|
|
// 快速绘制当前状态(跳过照片,提升流畅度)
|