From 8cd804564966135707b1ac96b5acb126f0f7209c Mon Sep 17 00:00:00 2001 From: yueliuli <1628111725@qq.com> Date: Fri, 24 Apr 2026 11:46:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=B6=E9=97=B4=E7=BA=BF?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=20-=20=E6=9B=B4=E6=96=B0=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E8=BD=B4=E6=93=8D=E4=BD=9C=E8=AF=B4=E6=98=8E=20-=20=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E6=92=AD=E6=94=BE=E5=A4=B4=E5=9C=A8=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E7=B2=97=E7=BB=86=E5=8F=98=E5=8C=96=20-=20?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BF=AB=E9=80=9F=E6=8B=96=E5=8A=A8=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=A4=B4=EF=BC=8C=E6=9D=BE=E5=BC=80=E9=BC=A0=E6=A0=87?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E6=92=AD=E6=94=BE=E5=A4=B4=E9=97=AA=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hazard_inspect/timeline/timeline.css | 12 ++++++- .../hazard_inspect/timeline/timeline.ts | 32 ++++++++++++------- .../hazard_inspect/timeline/timeline.vue | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/components/hazard_inspect/timeline/timeline.css b/src/components/hazard_inspect/timeline/timeline.css index 2b55bed..8010248 100644 --- a/src/components/hazard_inspect/timeline/timeline.css +++ b/src/components/hazard_inspect/timeline/timeline.css @@ -98,9 +98,19 @@ top: 0; bottom: 0; width: 2px; - background-color: #ef4444; z-index: 25; cursor: ew-resize; + transform: translateZ(0); +} + +.playhead::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 2px; + height: 100%; + background-color: #ef4444; } .playhead-indicator { diff --git a/src/components/hazard_inspect/timeline/timeline.ts b/src/components/hazard_inspect/timeline/timeline.ts index 005f3d6..aee1319 100644 --- a/src/components/hazard_inspect/timeline/timeline.ts +++ b/src/components/hazard_inspect/timeline/timeline.ts @@ -64,6 +64,7 @@ export function useTimeline( const isPlayheadDragging = ref(false) const isRulerDragging = ref(false) const isMounted = ref(false) + const displayFrame = ref(0) const dragStartX = ref(0) const scrollStartLeft = ref(0) const localCurrentFrame = ref(0) @@ -121,18 +122,16 @@ export function useTimeline( // 计算缩放前后的位置偏移 // console.log('container.scrollLeft', container.scrollLeft) if (playheadVisible) { - // 以播放头为中心缩放 const playheadX = playheadPosition - containerScrollLeft const newPlayheadPosition = props.currentFrame * newPxPerFrame - const newScrollLeft = newPlayheadPosition - playheadX + const newScrollLeft = Math.round(newPlayheadPosition - playheadX) container.scrollLeft = newScrollLeft } else { - // 以容器中心为中心缩放 const centerX = containerWidth / 2 const centerPosition = containerScrollLeft + centerX const newCenterPosition = centerPosition * (newPxPerFrame / oldPxPerFrame) - container.scrollLeft = newCenterPosition - centerX + container.scrollLeft = Math.round(newCenterPosition - centerX) } // 最后更新缩放值 @@ -175,9 +174,7 @@ export function useTimeline( } const playheadPos: ComputedRef = computed(() => { - const frame = isPlayheadDragging.value ? localCurrentFrame.value : props.currentFrame - const clampedFrame = Math.max(0, Math.min(frame, props.totalFrames - 1)) - return clampedFrame * pxPerFrame.value + return Math.round(displayFrame.value * pxPerFrame.value) }) const trackRows: ComputedRef = computed(() => { @@ -260,6 +257,15 @@ export function useTimeline( if (!timelineContainer.value) return e.preventDefault() + + if (e.shiftKey) { + const delta = e.deltaY || e.deltaX + const zoomDelta = delta > 0 ? -0.1 : 0.1 + const newZoom = pxPerFrame.value + zoomDelta + setZoom(newZoom) + return + } + const container = timelineContainer.value const delta = e.deltaY || e.deltaX container.scrollLeft += delta @@ -318,6 +324,7 @@ export function useTimeline( const frame = Math.floor(x / pxPerFrame.value) const clampedFrame = Math.max(0, Math.min(frame, props.totalFrames - 1)) localCurrentFrame.value = clampedFrame + displayFrame.value = clampedFrame emit('frameChange', clampedFrame) } @@ -330,13 +337,16 @@ export function useTimeline( const frame = Math.floor(x / pxPerFrame.value) const clampedFrame = Math.max(0, Math.min(frame, props.totalFrames - 1)) localCurrentFrame.value = clampedFrame + displayFrame.value = clampedFrame emit('frameChange', clampedFrame) } watch(() => props.currentFrame, () => { - if (!isPlayheadDragging.value) { - localCurrentFrame.value = props.currentFrame - } + if (isPlayheadDragging.value) + return + + displayFrame.value = props.currentFrame + nextTick(() => { if (!timelineContainer.value) return @@ -408,7 +418,7 @@ export function useTimeline( isDragging, isPlayheadDragging, isRulerDragging, - localCurrentFrame, + displayFrame, trackWidth, timeTicks, secondTicks, diff --git a/src/components/hazard_inspect/timeline/timeline.vue b/src/components/hazard_inspect/timeline/timeline.vue index 2d626fd..dadfb2c 100644 --- a/src/components/hazard_inspect/timeline/timeline.vue +++ b/src/components/hazard_inspect/timeline/timeline.vue @@ -50,7 +50,7 @@ onUnmounted(() => {