photo_view
photo_view copied to clipboard
Example for getting pixel location on image, on onTap
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!
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');
}
},
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?