Open stropitek opened 7 months ago
We probably should have another simpler component that only handles the pan/zoom part and is controlled.
[!NOTE]
This is a draft
We should reuse as much as possible the existing code implemented for the other components, and if needed refactor it to make it more reusable across components.
I understand that it might not be easy to navigate the existing code. Please feel completely free to ask questions while implementing this.
The current code has to following model for computing transformations. I came up with the terminology now so I haven't really used it in the code. But hope it can be hopeful to have a good mental model:
p_viewport
: position in viewport (pixels on user's screen)
p_reference
: reference position ("normalized" with respect to the resize strategy)
p_image
: image position (pixels in the target image)
f_resize
: transform applied by resize strategy
f_panzoom
: trtansform applied by the user (transform
prop below)
p_viewport = f_panzoom(p_reference);
p_reference = f_resize(p_image);
API I'm proposing:
const [transform, setTransform] = useState({scale: 1, translation: [0, 0]});
<PanZoom
// The PanZoom component is basically a div around the target image which style
// can be customized to fit into any particular layout outside of it.
style={{}}
className=""
transform={transform}
resizeStrategy="contain"
onDoubleClick={(event, helpers) => {
// Reset zoom level
setTransform({scale: 1, translation: [0, 0]});
// idea of cool feature:
// helpers.getPosition(event, 'image');
// With image segmentation, zoom on an object automatically
}}
onPanMove={(event, helpers) => {
// Called when moving the mouse during a click -> move -> release action
setTransform(transform => helpers.applyMovement(event, transform));
}}
onMouseWheel={(event, helpers) => {
// If you need it you can get data about where the event happened
const {x, y} = helpers.getPosition(event, 'image');
// User controls when it should `event.preventDefault` to disable regular scrolling
// And if zoom should happen only when `alt` key is pressed for example
const zoomFactor = event.deltaY > 0 ? 1.2 ? 1 / 1.2;
// Get the transform needed
setTransform(transform => helpers.applyZoomTowardsCenter(zoomFactor, transform));
}}
>
<TargetImage src="" />
</PanZoom>
It's could maybe be useful if helper methods can return coordinate information in different coordinate systems as defined above: viewport
, reference
, image
. Like the example above onDoubleClick
.
Other feature to consider later and questions:
onPanStart
and onPanEnd
lifecycle callbacks
To do this we need:
Ref: https://github.com/zakodium-oss/pixelium/issues/80