fix(zoom): address PR review — preview selected zoom + keyboard a11y
- VideoPlayback: while holding Preview, render the SELECTED zoom at full strength regardless of the playhead, instead of whatever findDominantRegion returns at currentTime (which is none/another zoom when the playhead is outside the selection). Uses getZoomScale/getRotation3D for the region's configured scale and 3D preset. - SettingsPanel: require both onZoomPreviewStart && onZoomPreviewEnd to render the button (full lifecycle), and add keyboard support — Space/Enter keydown (repeat-guarded) starts preview, keyup/blur ends it.
This commit is contained in:
@@ -944,13 +944,26 @@ export function SettingsPanel({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{zoomEnabled && (onZoomPreviewStart || onZoomPreviewEnd) && (
|
||||
{zoomEnabled && onZoomPreviewStart && onZoomPreviewEnd && (
|
||||
<Button
|
||||
type="button"
|
||||
onPointerDown={() => onZoomPreviewStart?.()}
|
||||
onPointerUp={() => onZoomPreviewEnd?.()}
|
||||
onPointerLeave={() => onZoomPreviewEnd?.()}
|
||||
onPointerCancel={() => onZoomPreviewEnd?.()}
|
||||
onPointerDown={() => onZoomPreviewStart()}
|
||||
onPointerUp={() => onZoomPreviewEnd()}
|
||||
onPointerLeave={() => onZoomPreviewEnd()}
|
||||
onPointerCancel={() => onZoomPreviewEnd()}
|
||||
onKeyDown={(e) => {
|
||||
if ((e.key === " " || e.key === "Enter") && !e.repeat) {
|
||||
e.preventDefault();
|
||||
onZoomPreviewStart();
|
||||
}
|
||||
}}
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === " " || e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
onZoomPreviewEnd();
|
||||
}
|
||||
}}
|
||||
onBlur={() => onZoomPreviewEnd()}
|
||||
className="h-7 w-full select-none rounded-md border border-white/[0.08] bg-white/[0.04] text-[10px] font-semibold text-slate-300 transition-all duration-150 ease-out hover:bg-white/[0.08] hover:text-slate-100 active:border-[#34B27B]/50 active:bg-[#34B27B] active:text-white cursor-pointer"
|
||||
>
|
||||
{t("zoom.previewHold")}
|
||||
|
||||
@@ -59,6 +59,8 @@ import {
|
||||
DEFAULT_CURSOR_SIZE,
|
||||
DEFAULT_CURSOR_SMOOTHING,
|
||||
DEFAULT_ROTATION_3D,
|
||||
getRotation3D,
|
||||
getZoomScale,
|
||||
isRotation3DIdentity,
|
||||
lerpRotation3D,
|
||||
rotation3DPerspective,
|
||||
@@ -1301,7 +1303,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
|
||||
let lastTransformIsIdentity = true;
|
||||
let lastPerspectiveValue = 0;
|
||||
const ticker = () => {
|
||||
const { region, strength, blendedScale, rotation3D, transition } = findDominantRegion(
|
||||
let { region, strength, blendedScale, rotation3D, transition } = findDominantRegion(
|
||||
zoomRegionsRef.current,
|
||||
currentTimeRef.current,
|
||||
{
|
||||
@@ -1310,6 +1312,21 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(
|
||||
},
|
||||
);
|
||||
|
||||
// While holding Preview, show the SELECTED zoom (what the settings panel
|
||||
// is editing) at full strength, independent of the playhead — otherwise
|
||||
// the preview reflects whatever region sits at currentTime, which may be
|
||||
// none or a different zoom when the playhead isn't inside the selection.
|
||||
if (isPreviewingZoomRef.current && selectedZoomIdRef.current) {
|
||||
const sel = zoomRegionsRef.current.find((r) => r.id === selectedZoomIdRef.current);
|
||||
if (sel) {
|
||||
region = sel;
|
||||
strength = 1;
|
||||
blendedScale = getZoomScale(sel);
|
||||
rotation3D = getRotation3D(sel);
|
||||
transition = null;
|
||||
}
|
||||
}
|
||||
|
||||
const defaultFocus = DEFAULT_FOCUS;
|
||||
let targetScaleFactor = 1;
|
||||
let targetFocus = defaultFocus;
|
||||
|
||||
Reference in New Issue
Block a user