mwcraig / ipyevents

A custom widget for returning mouse and keyboard events to Python. Documentation:
https://ipyevents.readthedocs.io/en/latest/index.html
BSD 3-Clause "New" or "Revised" License
112 stars 27 forks source link

How to obtain the coordinates of a click on the image when object_fit='contain'? #71

Open GuillaumeFavelier opened 2 years ago

GuillaumeFavelier commented 2 years ago

Hello maintainers and contributors of ipyevents :wave:


The context

I contribute to mne-python(opened issue) and I am working on integration into the Jupyter Notebook environment. The project has tight interactions between ipyevents, ipycanvas, ipyvtklink(opened issue) and ipywidgets, that's why I am not 100% sure it is the right place to open this issue but I will try to explain the unexpected behaviour I observe anyway.

Here is a demo of the final app in mne-python:

https://user-images.githubusercontent.com/18143289/153018183-dc8a8950-4eb0-4489-8022-e65b6e0813d1.mp4


The issue

Let's assume an image contained in an HBox called viewer and a VBox called right_dock containing multiple widgets in an Accordion folded by default. Both viewer and right_dock are in turn contained into an HBox called app which is finally displayed:

image

I would like to get the coordinates of the click in image when the layout is set to image.layout.object_fit = 'contain' (useful to preserve the aspect ratio).

image

Unfortunately, I think ipyevents is not aware of object_fit because the coordinates that I observe in my experiments are the same as if the image was 'stretched' to fit its container.

https://user-images.githubusercontent.com/18143289/154511832-dc41e328-37d4-47c0-93a2-5c74ae84c84b.mp4

Is there a way to obtain the real coordinates of a click on the image in this situation?


Minimum reproducible example

I share below a simplified example (inspired from the demo notebook):

```py from ipywidgets import Box, VBox, HBox, HTML, Image, Accordion from ipyevents import Event def gen_opts(n): return[HTML(f"option{i}") for i in range(n)] with open('images/gaussian_600_x_300.png', 'rb') as f: value = f.read() image = Image(value=value, format='png') image.layout.object_fit = 'contain' image.layout.border = '5px red solid' right_dock = Accordion([VBox(gen_opts(15))]) right_dock.set_title(0, "Right dock") right_dock.selected_index = None im_events = Event() im_events.source = image im_events.watched_events = ['click'] viewer = HBox([image]) red_layout(image) coordinates = HTML('

Click an image to see the click coordinates here

') def update_coords(event): coordinates.value = '

Clicked at ({}, {})

'.format(event['dataX'], event['dataY']) im_events.on_dom_event(update_coords) row = HBox([viewer, right_dock]) app = VBox([row, coordinates]) app ```

cc @larsoner, @banesullivan

mwcraig commented 2 years ago

Thanks for the report -- I'll try to track down the issue (I do think it is an ipyevents issue).

Also, awesome-looking tool you have developed 💯 !