Improves scroll interaction for sequence editor
- Scroll paning (`shift + scroll`) is now synced for the keyframe viewport, easing viewport and scrollbar (Closes #22) - Scroll zooming out (`ctrl + scroll down`) is now bounded to avoid zooming out to infinity (Closes #19) There is still some quirky behaviour when using scroll to zoom inwards. It does not seem to respect the `pivotPointInUnitSpace` correctly. I've tried fixing it, but I've hit a dead end.
This commit is contained in:
parent
4d49a8bdd6
commit
bf0367bd0d
2 changed files with 42 additions and 1 deletions
|
@ -7,6 +7,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
background: black;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import styled from 'styled-components'
|
||||||
import {useReceiveVerticalWheelEvent} from '@theatre/studio/panels/SequenceEditorPanel/VerticalScrollContainer'
|
import {useReceiveVerticalWheelEvent} from '@theatre/studio/panels/SequenceEditorPanel/VerticalScrollContainer'
|
||||||
import {pointerEventsAutoInNormalMode} from '@theatre/studio/css'
|
import {pointerEventsAutoInNormalMode} from '@theatre/studio/css'
|
||||||
import {useCursorLock} from '@theatre/studio/uiComponents/PointerEventsHandler'
|
import {useCursorLock} from '@theatre/studio/uiComponents/PointerEventsHandler'
|
||||||
|
import type {IRange} from '@theatre/shared/utils/types'
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -192,7 +193,8 @@ function useHandlePanAndZoom(
|
||||||
)
|
)
|
||||||
|
|
||||||
const oldRange = val(layoutP.clippedSpace.range)
|
const oldRange = val(layoutP.clippedSpace.range)
|
||||||
const scaleFactor = 1 + event.deltaY * 0.03
|
const delta = normalize(event.deltaY, [-50, 50])
|
||||||
|
const scaleFactor = 1 + delta * 0.03
|
||||||
|
|
||||||
const newRange = mapValues(oldRange, (originalPos) => {
|
const newRange = mapValues(oldRange, (originalPos) => {
|
||||||
return (
|
return (
|
||||||
|
@ -201,6 +203,33 @@ function useHandlePanAndZoom(
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Set maximum scroll points based on the sequence length.
|
||||||
|
// This is to avoid zooming out to infinity.
|
||||||
|
const sequenceLength = val(layoutP.sheet).getSequence().length
|
||||||
|
const maxEnd = sequenceLength + sequenceLength * 0.25
|
||||||
|
|
||||||
|
val(layoutP.clippedSpace.setRange)(
|
||||||
|
normalizeRange(newRange, [0, maxEnd]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// paning
|
||||||
|
else if (event.shiftKey) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
const sequenceLength = val(layoutP.sheet).getSequence().length
|
||||||
|
const oldRange = val(layoutP.clippedSpace.range)
|
||||||
|
const windowSize = oldRange.end - oldRange.start
|
||||||
|
const speed = windowSize / sequenceLength
|
||||||
|
|
||||||
|
const delta = normalize(event.deltaY, [-50, 50])
|
||||||
|
const scaleFactor = delta * 0.05 * speed
|
||||||
|
|
||||||
|
const newRange = mapValues(
|
||||||
|
oldRange,
|
||||||
|
(originalPos) => originalPos + scaleFactor,
|
||||||
|
)
|
||||||
|
|
||||||
val(layoutP.clippedSpace.setRange)(newRange)
|
val(layoutP.clippedSpace.setRange)(newRange)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +246,17 @@ function useHandlePanAndZoom(
|
||||||
}, [node, layoutP])
|
}, [node, layoutP])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalize(value: number, [min, max]: [min: number, max: number]) {
|
||||||
|
return Math.max(Math.min(value, max), min)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRange(
|
||||||
|
range: IRange<number>,
|
||||||
|
minMax: [min: number, max: number],
|
||||||
|
) {
|
||||||
|
return mapValues(range, (pos) => normalize(pos, minMax))
|
||||||
|
}
|
||||||
|
|
||||||
function useUpdateScrollFromClippedSpaceRange(
|
function useUpdateScrollFromClippedSpaceRange(
|
||||||
layoutP: Pointer<SequenceEditorPanelLayout>,
|
layoutP: Pointer<SequenceEditorPanelLayout>,
|
||||||
node: HTMLDivElement | null,
|
node: HTMLDivElement | null,
|
||||||
|
|
Loading…
Reference in a new issue