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(() => {