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

Example for getting pixel location on image, on onTap #546

Open
ElecSmurf opened this issue Nov 25, 2023 · 2 comments
Open

Example for getting pixel location on image, on onTap #546

ElecSmurf opened this issue Nov 25, 2023 · 2 comments

Comments

@ElecSmurf
Copy link

Hi,

I'm using the PhotoView.customChild with a background image and a customPaint (stacked) over it.
This is wrapped in a Listener to have scrolling with the mousewheel.

That is working great, love the performance and flexibility of your solution!

I'm now struggling however to get the pixel location on the image from an onTap event.
I tried lots of ways, but don't seem to get the correct coords.

  • I know the pixelSize of my image
  • I can get the size the image is rendered in => context.findRenderObject()?.paintBounds.size
  • but can't get to the location with neither local or global position (which seem to always have the same values for me)

Is there any documentation or example on this that could help me?

Thanks in advance!

@ElecSmurf
Copy link
Author

I have figured it out, depending on the image ratio vs available screen ratio, there can be either in width or height some empty space that needs to be taken into account.
This is my solution should it help someone:

onPointerHover: (PointerHoverEvent event) {
   Size? sizeOnScreen = context.findRenderObject()?.paintBounds.size;
   double widthFactor = (sizeOnScreen?.width ?? 1) / imageWidth;
   double heightFactor = (sizeOnScreen?.height ?? 1) / imageHeight;
   if (widthFactor < heightFactor) {
      double x = event.localPosition.dx / widthFactor;
      double imageRatio = imageHeight / imageWidth;
      double heightOnScreen = imageRatio * (sizeOnScreen?.width ?? 1);
      double heightTopSpace = ((sizeOnScreen?.height ?? 1) - heightOnScreen) / 2;
      double y = (event.localPosition.dy - heightTopSpace) / widthFactor;
      print('$x,$y');
   } else {
      double y = event.localPosition.dy / heightFactor;
      double imageRatio = imageWidth / imageHeight;
      double widthOnScreen = imageRatio * (sizeOnScreen?.height ?? 1);
      double widthSideSpace =
      ((sizeOnScreen?.width ?? 1) - widthOnScreen) / 2;
      double x = (event.localPosition.dx - widthSideSpace) / heightFactor;
      print('$x,$y');
   }
},

@ElecSmurf
Copy link
Author

ElecSmurf commented Nov 26, 2023

After good night of sleep I found some errors and refactored to this solution.
This works for all cases.

Offset? getPixelPosition(Offset mouseLocalLocation) {
   Size? screenSize = context.findRenderObject()?.paintBounds.size;
   double zoomFactor = _controller.scale ?? 1;

   if (screenSize != null && _controller.scale != null) {
      double xRelToCenScreenSpace = (screenSize.width / 2) - mouseLocalLocation.dx;
      double yRelToCenScreenSpace = (screenSize.height / 2) - mouseLocalLocation.dy;

      double x = ((imageWidth / 2) - (xRelToCenScreenSpace / zoomFactor)) - (_controller.position.dx / zoomFactor);
      double y = (imageHeight / 2) - (yRelToCenScreenSpace / zoomFactor) - (_controller.position.dy / zoomFactor);

      if (x < 0 || y < 0 || x > imageWidth || y > imageHeight) {
         return null;
      } else {
         print('Pos: ${x.toStringAsFixed(2)},${y.toStringAsFixed(2)}');
         return Offset(x, y);
      }
   }
   return null;
}

Maybe this method can be added as a static (helper) method on the controler?

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