Zoom and pan the preview with the wheel, and step a parameter from its ruler
Cursor over the image: the wheel zooms about the pointer, and a drag pans, both clamped to the contain-fit of the loaded bitmap so the photo can never be lost off-screen. Cursor over an open parameter ruler: the wheel moves that parameter by one step, clamped to its min/max. While the crop frame is being dragged the wheel keeps resizing the crop instead, and APPLY puts the view back on the fit.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
// One strip at a time — the same shape as the phone's AdjustmentPanel: a ruler
|
||||
// row for the open slider, an options strip for the open group, then the tab's
|
||||
// chip row. Chip labels are the phone's own strings (they are not translated
|
||||
@@ -53,8 +55,27 @@ export function ChipRow({ chips }: { chips: ChipDef[] }) {
|
||||
}
|
||||
|
||||
export function SliderRow({ slider }: { slider: SliderDef }) {
|
||||
// The wheel belongs to the open ruler: one notch is one step, held inside the
|
||||
// parameter's own range. The listener is native because React's is passive —
|
||||
// the panel must not scroll away under the cursor while the value moves.
|
||||
const rowRef = useRef<HTMLDivElement>(null);
|
||||
const live = useRef(slider);
|
||||
live.current = slider;
|
||||
useEffect(() => {
|
||||
const el = rowRef.current;
|
||||
if (!el) return;
|
||||
const onWheel = (e: WheelEvent) => {
|
||||
e.preventDefault();
|
||||
const s = live.current;
|
||||
const step = s.step || 1;
|
||||
const next = Math.min(s.max, Math.max(s.min, s.value + (e.deltaY < 0 ? step : -step)));
|
||||
if (next !== s.value) s.onChange(next);
|
||||
};
|
||||
el.addEventListener('wheel', onWheel, { passive: false });
|
||||
return () => el.removeEventListener('wheel', onWheel);
|
||||
}, []);
|
||||
return (
|
||||
<div className="slider-row">
|
||||
<div className="slider-row" ref={rowRef}>
|
||||
<button type="button" className="back" onClick={slider.onBack} aria-label="back"><</button>
|
||||
<div className="ruler">
|
||||
<div className="head">
|
||||
|
||||
Reference in New Issue
Block a user