feat: implement time snapping to 100ms intervals for improved sound placement accuracy
This commit is contained in:
@@ -79,6 +79,14 @@ export function SequencerPage() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Helper function to snap time to 100ms intervals with improved precision
|
||||
const snapToGrid = useCallback((timeInSeconds: number): number => {
|
||||
const snapIntervalMs = 100 // 100ms snap interval
|
||||
const timeInMs = Math.max(0, timeInSeconds * 1000) // Ensure non-negative
|
||||
const snappedMs = Math.round(timeInMs / snapIntervalMs) * snapIntervalMs
|
||||
return Math.max(0, snappedMs / 1000) // Convert back to seconds, ensure non-negative
|
||||
}, [])
|
||||
|
||||
// Update drag over info based on current mouse position and over target
|
||||
useEffect(() => {
|
||||
if (draggedItem && currentMousePos && (draggedItem.type === 'sound' || draggedItem.type === 'placed-sound')) {
|
||||
@@ -93,8 +101,12 @@ export function SequencerPage() {
|
||||
currentMousePos.y >= rect.top &&
|
||||
currentMousePos.y <= rect.bottom
|
||||
) {
|
||||
const x = currentMousePos.x - rect.left
|
||||
setDragOverInfo({ trackId: track.id, x: Math.max(0, x) })
|
||||
const rawX = currentMousePos.x - rect.left
|
||||
// Apply snapping to the drag over position for consistency
|
||||
const rawTimeSeconds = rawX / state.zoom
|
||||
const snappedTimeSeconds = snapToGrid(rawTimeSeconds)
|
||||
const snappedX = snappedTimeSeconds * state.zoom
|
||||
setDragOverInfo({ trackId: track.id, x: Math.max(0, snappedX) })
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -104,7 +116,7 @@ export function SequencerPage() {
|
||||
} else {
|
||||
setDragOverInfo(null)
|
||||
}
|
||||
}, [draggedItem, currentMousePos, state.tracks])
|
||||
}, [draggedItem, currentMousePos, state.tracks, state.zoom, snapToGrid])
|
||||
|
||||
const handleDragEnd = useCallback((event: DragEndEvent) => {
|
||||
const { active, over } = event
|
||||
@@ -113,10 +125,10 @@ export function SequencerPage() {
|
||||
|
||||
// Handle sound drop from library to track
|
||||
if (dragData?.type === 'sound' && overData?.type === 'track') {
|
||||
// Use precise drop position if available (convert from pixels to milliseconds)
|
||||
// Use precise drop position if available (dragOverInfo.x is already snapped)
|
||||
let startTime = 0
|
||||
if (dragOverInfo && dragOverInfo.trackId === overData.trackId) {
|
||||
startTime = Math.max(0, (dragOverInfo.x / state.zoom) * 1000) // Convert seconds to milliseconds
|
||||
startTime = Math.max(0, (dragOverInfo.x / state.zoom) * 1000) // Convert to milliseconds
|
||||
}
|
||||
|
||||
const soundDuration = dragData.sound.duration // Already in milliseconds
|
||||
@@ -149,10 +161,10 @@ export function SequencerPage() {
|
||||
|
||||
// Handle moving placed sounds within tracks
|
||||
if (dragData?.type === 'placed-sound' && overData?.type === 'track') {
|
||||
// Use precise drop position if available (convert from pixels to milliseconds)
|
||||
// Use precise drop position if available (dragOverInfo.x is already snapped)
|
||||
let startTime = dragData.startTime || 0
|
||||
if (dragOverInfo && dragOverInfo.trackId === overData.trackId) {
|
||||
startTime = Math.max(0, (dragOverInfo.x / state.zoom) * 1000) // Convert seconds to milliseconds
|
||||
startTime = Math.max(0, (dragOverInfo.x / state.zoom) * 1000) // Convert to milliseconds
|
||||
}
|
||||
|
||||
// Restrict placement to within track duration (all in milliseconds)
|
||||
@@ -170,7 +182,10 @@ export function SequencerPage() {
|
||||
if (track.id === sourceTrackId && sourceTrackId === targetTrackId) {
|
||||
// Moving within the same track - just update position
|
||||
const updatedSound: PlacedSound = {
|
||||
...dragData,
|
||||
id: dragData.id,
|
||||
soundId: dragData.soundId,
|
||||
name: dragData.name,
|
||||
duration: dragData.duration,
|
||||
startTime,
|
||||
trackId: targetTrackId,
|
||||
}
|
||||
@@ -189,7 +204,10 @@ export function SequencerPage() {
|
||||
} else if (track.id === targetTrackId) {
|
||||
// Add to target track (different track move)
|
||||
const updatedSound: PlacedSound = {
|
||||
...dragData,
|
||||
id: dragData.id,
|
||||
soundId: dragData.soundId,
|
||||
name: dragData.name,
|
||||
duration: dragData.duration,
|
||||
startTime,
|
||||
trackId: targetTrackId,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user