Skip to content

Commit

Permalink
Clicked point to Lonboard map (#671)
Browse files Browse the repository at this point in the history
This PR adds a new property to the Lonboard map that holds a tuple for
the coordinate where the user last clicked on the map. It is not
implemented as an .on_click(), as was
[discussed](#633),
but I think it accomplishes the same functionality (and may actually
have more utility this way). hopefully this is an acceptable pattern,
but if not, let me know and I'll see what I can do.
  • Loading branch information
ATL2001 authored Dec 17, 2024
1 parent 29d5d0f commit 3ff75dc
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 2 deletions.
Binary file added assets/clicked-point.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions examples/clicked-point.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e328a21f-5254-42ee-9683-136561d96886",
"metadata": {},
"source": [
"# Clicked point\n",
"\n",
"This notebook demonstrates how you can access the coordinate of the most recent click on a Lonboard map and update a set of widgets to display the x and y coordinates using the [`ipywidgets.observe`](https://ipywidgets.readthedocs.io/en/8.1.5/examples/Widget%20Events.html#traitlet-events) method."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f986a64e-269f-4966-93b0-cfa5bf1ba882",
"metadata": {},
"outputs": [],
"source": [
"from typing import Tuple\n",
"\n",
"import ipywidgets as widgets\n",
"\n",
"from lonboard import Map\n",
"\n",
"## Create a Lonboard map and two widgets to display the coordinate\n",
"m = Map(layers=[])\n",
"clicked_x_display = widgets.FloatText(description=\"last clicked x:\")\n",
"clicked_y_display = widgets.FloatText(description=\"last clicked y:\")\n",
"\n",
"def on_map_click(coordinate:Tuple[float, float]) -> None:\n",
" x,y = coordinate\n",
" clicked_x_display.value = x\n",
" clicked_y_display.value = y\n",
"m.on_click(on_map_click)\n",
"\n",
"## show the widgets\n",
"widgets.VBox([\n",
" m,\n",
" clicked_x_display,\n",
" clicked_y_display\n",
"])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "lonboard",
"language": "python",
"name": "lonboard"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
2 changes: 1 addition & 1 deletion examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
- [Rivers in Asia ![](../assets/rivers-asia.jpg)](../examples/map_challenge/6-asia/) using [`PathLayer`](../api/layers/path-layer)
- [Inflation Reduction Act Projects ![](../assets/column-layer.jpg)](../examples/column-layer/) using [`ColumnLayer`](../api/layers/column-layer)
- [Linked Maps ![](../assets/linked-maps.gif)](../examples/linked-maps/)

- [Clicked Point ![](../assets/clicked-point.png)](../examples/clicked-point/)
</div>

## Integrations
Expand Down
40 changes: 39 additions & 1 deletion lonboard/_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import sys
from io import StringIO
from pathlib import Path
from typing import IO, TYPE_CHECKING, Optional, Sequence, TextIO, Union, overload
from typing import IO, TYPE_CHECKING, List, Optional, Sequence, TextIO, Union, overload

import ipywidgets
import traitlets
import traitlets as t
from ipywidgets import CallbackDispatcher
from ipywidgets.embed import embed_minimal_html

from lonboard._base import BaseAnyWidget
Expand Down Expand Up @@ -100,7 +101,40 @@ def __init__(
if isinstance(layers, BaseLayer):
layers = [layers]

def _handle_anywidget_dispatch(
widget: ipywidgets.Widget, msg: Union[str, list, dict], buffers: List[bytes]
) -> None:
if msg.get("kind") == "on-click":
self._click_handlers(tuple(msg.get("coordinate")))

super().__init__(layers=layers, **kwargs)
self._click_handlers = CallbackDispatcher()
self.on_msg(_handle_anywidget_dispatch)

def on_click(self, callback, remove=False):
"""Register a callback to execute when the map is clicked.
The callback will be called with one argument, a tuple of the coordinate
clicked (x,y)/(Longitude/Latitude).
Parameters
----------
remove: bool (optional)
Set to true to remove the callback from the list of callbacks.
!!! note
If the map is zoomed to a very large scale and can see the earth wrapped
around, it is possible the coordinate's x/Longitude value may be greater
than or less than expected. Example: If you can see Paris, France three
times in the map, and you click on the Paris in the middle, it will show an
X coordinate of 2, but the Paris on the left of the map will report an X
coordinate of -358, and the Paris on the right of the map will report an
X coordinate of 362.
"""
self._click_handlers.register_callback(callback, remove=remove)
self._has_click_handlers = len(self._click_handlers.callbacks) > 0

_esm = bundler_output_dir / "index.js"
_css = bundler_output_dir / "index.css"
Expand Down Expand Up @@ -128,6 +162,10 @@ def __init__(
once it's been initially rendered.
"""
_has_click_handlers = t.Bool(default_value=False, allow_none=False).tag(sync=True)
"""
Indicates if a click handler has been registered.
"""

_height = t.Int(default_value=DEFAULT_HEIGHT, allow_none=True).tag(sync=True)
"""Height of the map in pixels.
Expand Down
5 changes: 5 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ function App() {
const onMapClickHandler = useCallback((info: PickingInfo) => {
// We added this flag to prevent the hover event from firing after a
// click event.
if (typeof info.coordinate !== "undefined") {
if (model.get("_has_click_handlers")) {
model.send({ kind: "on-click", coordinate: info.coordinate });
}
}
setJustClicked(true);
actorRef.send({
type: "Map click event",
Expand Down

0 comments on commit 3ff75dc

Please sign in to comment.