refactor(TimelinePanel): 抽取 usePlayheadDrag hook
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { useState, useCallback, useEffect, useRef } from "react"
|
||||
|
||||
interface UsePlayheadDragOptions {
|
||||
/** 当前播放时间(秒) */
|
||||
currentTime: number
|
||||
/** 缩放:每秒像素数 */
|
||||
pps: number
|
||||
/** 总时长(秒) */
|
||||
totalDuration: number
|
||||
/** 播放头跳转回调 */
|
||||
onSeek?: (time: number) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放头拖拽 Hook
|
||||
* 封装播放头的 mousedown/mousemove/mouseup 拖拽逻辑
|
||||
*/
|
||||
export const usePlayheadDrag = ({
|
||||
pps,
|
||||
totalDuration,
|
||||
onSeek,
|
||||
}: UsePlayheadDragOptions) => {
|
||||
const [playheadDragging, setPlayheadDragging] = useState(false)
|
||||
const trackRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
/* ── 播放头拖拽全局 mousemove/mouseup ── */
|
||||
useEffect(() => {
|
||||
if (!playheadDragging) return
|
||||
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
const trackEl = trackRef.current
|
||||
if (!trackEl) return
|
||||
const rect = trackEl.getBoundingClientRect()
|
||||
const x = e.clientX - rect.left + trackEl.scrollLeft
|
||||
const time = Math.max(0, Math.min(x / pps, totalDuration))
|
||||
onSeek?.(Math.round(time * 10) / 10)
|
||||
}
|
||||
|
||||
const handleMouseUp = () => {
|
||||
setPlayheadDragging(false)
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", handleMouseMove)
|
||||
document.addEventListener("mouseup", handleMouseUp)
|
||||
return () => {
|
||||
document.removeEventListener("mousemove", handleMouseMove)
|
||||
document.removeEventListener("mouseup", handleMouseUp)
|
||||
}
|
||||
}, [playheadDragging, pps, totalDuration, onSeek])
|
||||
|
||||
/* ── 播放头拖拽开始 ── */
|
||||
const handlePlayheadMouseDown = useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setPlayheadDragging(true)
|
||||
}, [])
|
||||
|
||||
/* ── 标尺点击跳转播放头 ── */
|
||||
const handleRulerClick = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect()
|
||||
const x = e.clientX - rect.left
|
||||
const time = Math.max(0, Math.min(x / pps, totalDuration))
|
||||
onSeek?.(Math.round(time * 10) / 10)
|
||||
},
|
||||
[pps, totalDuration, onSeek],
|
||||
)
|
||||
|
||||
return {
|
||||
trackRef,
|
||||
playheadDragging,
|
||||
handlePlayheadMouseDown,
|
||||
handleRulerClick,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user