From c5c31e80881693af22528b765ac794d3cfc09f94 Mon Sep 17 00:00:00 2001 From: DevOps Date: Wed, 24 Dec 2025 01:01:54 +0800 Subject: [PATCH] Fix iOS Safari double-tap zoom issue on score modification buttons Problem: - Rapid tapping on +0.001/-0.001 buttons triggered page zoom on iOS Safari - Previous solutions (viewport meta, touch-action: manipulation) were ineffective Solution implemented: 1. Enhanced global touch event handling in index.html: - Added comprehensive gesture event prevention (gesturestart/change/end) - Improved touchend debouncing with stopPropagation - Added specific CSS rules for button elements with touch-action: none 2. Modified button interaction in modify-score.vue: - Replaced @click events with @touchstart/@touchend handlers - Added preventDefault and stopPropagation on touch events - Implemented 100ms debounce to prevent rapid successive touches - Added pointer-events: none to child elements to ensure touch targets - Changed touch-action from 'manipulation' to 'none' for complete control Technical details: - touch-action: none completely disables browser touch gestures - Event handlers use { passive: false } to allow preventDefault - Debounce mechanism prevents accidental double-triggers - Child elements have pointer-events: none to ensure parent handles all touches Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- index.html | 36 +++++++++++++++-- pages/modify-score/modify-score.vue | 60 +++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 57f643c..d092c50 100644 --- a/index.html +++ b/index.html @@ -12,22 +12,52 @@ -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; } + + /* 针对按钮元素禁用所有触摸动作 */ + button, .control-btn, [class*="btn"] { + touch-action: none !important; + -webkit-user-select: none !important; + user-select: none !important; + } diff --git a/pages/modify-score/modify-score.vue b/pages/modify-score/modify-score.vue index b12e37f..81c2aa0 100644 --- a/pages/modify-score/modify-score.vue +++ b/pages/modify-score/modify-score.vue @@ -50,7 +50,11 @@ - + -0.001 @@ -60,7 +64,11 @@ 可不改 - + +0.001 @@ -114,7 +122,9 @@ export default { originalScore: 8.000, note: '', minScore: 5.0, - maxScore: 10.0 + maxScore: 10.0, + lastTouchTime: 0, + touchDebounceDelay: 100 } }, @@ -199,6 +209,44 @@ export default { uni.navigateBack() }, + handleTouchStart(e) { + // 阻止默认行为,防止触发双击缩放 + e.preventDefault() + e.stopPropagation() + }, + + handleDecreaseTouch(e) { + // 阻止默认行为和事件冒泡 + e.preventDefault() + e.stopPropagation() + + // 防抖处理 + const now = Date.now() + if (now - this.lastTouchTime < this.touchDebounceDelay) { + return + } + this.lastTouchTime = now + + // 执行减分逻辑 + this.decreaseScore() + }, + + handleIncreaseTouch(e) { + // 阻止默认行为和事件冒泡 + e.preventDefault() + e.stopPropagation() + + // 防抖处理 + const now = Date.now() + if (now - this.lastTouchTime < this.touchDebounceDelay) { + return + } + this.lastTouchTime = now + + // 执行加分逻辑 + this.increaseScore() + }, + decreaseScore() { if (this.currentScore > this.minScore) { this.currentScore = parseFloat((this.currentScore - 0.001).toFixed(3)) @@ -459,10 +507,11 @@ export default { } .control-btn { - touch-action: manipulation; + touch-action: none; -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none; + -webkit-touch-callout: none; width: 140rpx; height: 140rpx; display: flex; @@ -471,6 +520,7 @@ export default { justify-content: center; background-color: #F5F5F5; border-radius: 12rpx; + cursor: pointer; } .control-btn.decrease { @@ -484,6 +534,7 @@ export default { .btn-symbol { font-size: 48rpx; font-weight: 300; + pointer-events: none; } .control-btn.decrease .btn-symbol { @@ -497,6 +548,7 @@ export default { .btn-value { font-size: 24rpx; margin-top: 8rpx; + pointer-events: none; } .control-btn.decrease .btn-value {