diff --git a/playground/src/views/question-bank/task-mgr/paper-explain.vue b/playground/src/views/question-bank/task-mgr/paper-explain.vue index 5d60813..22a2c81 100644 --- a/playground/src/views/question-bank/task-mgr/paper-explain.vue +++ b/playground/src/views/question-bank/task-mgr/paper-explain.vue @@ -157,6 +157,59 @@ function onResizeStart(e: MouseEvent) { document.addEventListener('mouseup', onMouseUp) } +// ======================== 讲解区缩放 ======================== +const MIN_ZOOM_SCALE = 0.7 +const MAX_ZOOM_SCALE = 2.5 +const zoomScale = ref(1) +const zoomPercent = computed(() => Math.round(zoomScale.value * 100)) +let pinchStartDistance = 0 +let pinchStartScale = 1 + +function clampZoomScale(scale: number) { + return Math.min(MAX_ZOOM_SCALE, Math.max(MIN_ZOOM_SCALE, scale)) +} + +function getTouchDistance(touches: TouchList) { + const first = touches[0] + const second = touches[1] + if (!first || !second) return 0 + return Math.hypot( + first.clientX - second.clientX, + first.clientY - second.clientY, + ) +} + +function onZoomTouchStart(e: TouchEvent) { + if (e.touches.length !== 2) return + pinchStartDistance = getTouchDistance(e.touches) + pinchStartScale = zoomScale.value +} + +function onZoomTouchMove(e: TouchEvent) { + if (e.touches.length !== 2 || !pinchStartDistance) return + e.preventDefault() + const distance = getTouchDistance(e.touches) + zoomScale.value = clampZoomScale( + pinchStartScale * (distance / pinchStartDistance), + ) +} + +function onZoomTouchEnd(e: TouchEvent) { + if (e.touches.length >= 2) return + pinchStartDistance = 0 +} + +function onZoomWheel(e: WheelEvent) { + if (!e.ctrlKey && !e.metaKey) return + e.preventDefault() + const delta = e.deltaY > 0 ? -0.08 : 0.08 + zoomScale.value = clampZoomScale(zoomScale.value + delta) +} + +function resetZoom() { + zoomScale.value = 1 +} + // ======================== 讲解模式 ======================== const currentIndex = ref(0) @@ -172,6 +225,7 @@ function getTitleKey(item: any) { async function enterExplaining() { initLeftWidth() + resetZoom() phase.value = 'explaining' currentIndex.value = 0 await callExplainApi(1) @@ -333,37 +387,48 @@ async function getTitleStudentInfo(titleId: string, markType: number) {