Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controlled PanZoom component #119

Open
stropitek opened this issue Feb 6, 2024 · 2 comments
Open

Controlled PanZoom component #119

stropitek opened this issue Feb 6, 2024 · 2 comments
Assignees

Comments

@stropitek
Copy link
Contributor

To do this we need:

  • To call the zoom callback during the pan action on every mouse move, not just when releasing the mouse.
  • To opt out of calling the callback when sending a new zoom to avoid an infinite loop of updates. Or maybe just to make sure the callback is not called when the zoom has not changed.

Ref: zakodium-oss/pixelium#80

@stropitek stropitek changed the title Sync zoom of 2 rois Sync zoom of 2 react-roi Feb 6, 2024
@stropitek
Copy link
Contributor Author

We probably should have another simpler component that only handles the pan/zoom part and is controlled.

@stropitek stropitek changed the title Sync zoom of 2 react-roi Controlled PanZoom component Feb 9, 2024
@stropitek
Copy link
Contributor Author

stropitek commented Feb 9, 2024

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:

  • Callback when container size changes. Could apply transform to keep center at the center.
  • onPanStart and onPanEnd lifecycle callbacks
  • How do we zoom into an image with a button outside of the panzoom component? We need a ref on the container to know the viewport coordinates of the center of the container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant