Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit290076e

Browse files
authored
feat: tooltips (#1263)
* stand-alone tooltips* listen to location and content changes* bind tooltip to Layer* listen to tooltip changes* doc for tooltip* remove outdated comment* updated doc
1 parenteceb588 commit290076e

File tree

5 files changed

+217
-1
lines changed

5 files changed

+217
-1
lines changed

‎docs/layers/tooltip.rst‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
Tooltip
2+
=====
3+
4+
Example
5+
-------
6+
7+
..jupyter-execute::
8+
9+
from ipyleaflet import Map, Tooltip, Marker, Polygon, Circle
10+
11+
m = Map(center=(51.505,-0.09), zoom=13)
12+
13+
standalone_tooltip = Tooltip(
14+
location=[51.5, -0.09],
15+
content="Hello world!<br />This is a nice tooltip.",
16+
offset=[-30,50], # Offset in pixels
17+
permanent=False, # The default is False, in which case you can remove the tooltip by clicking anywhere on the map.
18+
direction='bottom', # Default is 'auto'
19+
)
20+
21+
marker_tooltip = Tooltip(
22+
content="I'm a marker tooltip! 👋<br>Appears on hover.",
23+
)
24+
25+
marker = Marker(
26+
location=[51.5, -0.09],
27+
draggable=False,
28+
tooltip=marker_tooltip,
29+
)
30+
31+
polygon = Polygon(
32+
locations= [
33+
[51.509, -0.08],
34+
[51.503, -0.06],
35+
[51.51, -0.047]
36+
])
37+
38+
polygon_tooltip = Tooltip(
39+
content = "Polygon's Permanent Tooltip 🗺️",
40+
permanent = True,
41+
direction = 'center', # Centers the tooltip on the polygon
42+
)
43+
44+
polygon.tooltip = polygon_tooltip
45+
46+
circle = Circle(
47+
location = [51.515, -0.1],
48+
radius = 500,
49+
color = 'green',
50+
fillColor = '#0f3',
51+
fillOpacity = 0.5,
52+
tooltip = Tooltip(
53+
content = "Sticky Tooltip here! 📍<br>Stays with the mouse.",
54+
sticky = True,
55+
)
56+
)
57+
58+
m.add(standalone_tooltip)
59+
m.add(marker)
60+
m.add(polygon)
61+
m.add(circle)
62+
63+
m
64+
65+
66+
Attributes and methods
67+
----------------------
68+
69+
..autoclass::ipyleaflet.leaflet.Tooltip
70+
:members:

‎python/ipyleaflet/ipyleaflet/leaflet.py‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ class Layer(Widget, InteractMixin):
175175
Make Leaflet-Geoman ignore the layer, so it cannot modify it.
176176
snap_ignore: boolean
177177
Make Leaflet-Geoman snapping ignore the layer, so it is not used as a snap target when editing.
178+
tooltip: Tooltip widget
179+
Tooltip widget to bind to the layer.
178180
"""
179181

180182
_view_name=Unicode("LeafletLayerView").tag(sync=True)
@@ -196,6 +198,10 @@ class Layer(Widget, InteractMixin):
196198
popup_max_height=Int(default_value=None,allow_none=True).tag(sync=True)
197199
pane=Unicode("").tag(sync=True)
198200

201+
tooltip=Instance(Widget,allow_none=True,default_value=None).tag(
202+
sync=True,**widget_serialization
203+
)
204+
199205
options=List(trait=Unicode()).tag(sync=True)
200206
subitems=Tuple().tag(trait=Instance(Widget),sync=True,**widget_serialization)
201207

@@ -640,6 +646,43 @@ def close_popup(self):
640646
self.send({"msg":"close"})
641647

642648

649+
classTooltip(UILayer):
650+
"""Tooltip class.
651+
652+
Used to display small texts on top of map layers.
653+
654+
Attributes
655+
----------
656+
location: tuple, default None
657+
Optional tuple containing the latitude/longitude of the stand-alone tooltip.
658+
content: str, default ""
659+
The text to show inside the tooltip
660+
offset: tuple, default (0, 0)
661+
Optional offset of the tooltip position (in pixels).
662+
direction: str, default 'auto'
663+
Direction where to open the tooltip.
664+
Possible values are: right, left, top, bottom, center, auto.
665+
auto will dynamically switch between right and left according
666+
to the tooltip position on the map.
667+
permanent: bool, default False
668+
Whether to open the tooltip permanently or only on mouseover.
669+
sticky: bool, default False
670+
If true, the tooltip will follow the mouse instead of being fixed at the feature center.
671+
This option only applies when binding the tooltip to a Layer, not as stand-alone.
672+
"""
673+
_view_name=Unicode("LeafletTooltipView").tag(sync=True)
674+
_model_name=Unicode("LeafletTooltipModel").tag(sync=True)
675+
676+
location=List(allow_none=True,default_value=None).tag(sync=True)
677+
678+
# Options
679+
content=Unicode('').tag(sync=True,o=True)
680+
offset=List(def_loc).tag(sync=True,o=True)
681+
direction=Unicode('auto').tag(sync=True,o=True)
682+
permanent=Bool(False).tag(sync=True,o=True)
683+
sticky=Bool(False).tag(sync=True,o=True)
684+
685+
643686
classRasterLayer(Layer):
644687
"""Abstract RasterLayer class.
645688

‎python/jupyter_leaflet/src/jupyter-leaflet.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export * from './layers/Popup';
2727
export*from'./layers/RasterLayer';
2828
export*from'./layers/Rectangle';
2929
export*from'./layers/TileLayer';
30+
export*from'./layers/Tooltip';
3031
export*from'./layers/VectorLayer';
3132
export*from'./layers/VectorTileLayer';
3233
export*from'./layers/Velocity';

‎python/jupyter_leaflet/src/layers/Layer.ts‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
}from'@jupyter-widgets/base';
1010
import{IMessageHandler,MessageLoop}from'@lumino/messaging';
1111
import{Widget}from'@lumino/widgets';
12-
import{Control,Layer,LeafletMouseEvent,Popup}from'leaflet';
12+
import{Control,Layer,LeafletMouseEvent,Popup,Tooltip}from'leaflet';
1313
import{LeafletControlView,LeafletMapView}from'../jupyter-leaflet';
1414
importLfrom'../leaflet';
1515
import{LeafletWidgetView}from'../utils';
@@ -29,6 +29,7 @@ export interface ILeafletLayerModel {
2929
popup_max_width:number;
3030
popup_max_height:number|null;
3131
pane:string;
32+
tooltip:WidgetModel|null;
3233
subitems:Layer[];
3334
pm_ignore:boolean;
3435
snap_ignore:boolean;
@@ -55,13 +56,15 @@ export class LeafletLayerModel extends WidgetModel {
5556
subitems:[],
5657
pm_ignore:true,
5758
snap_ignore:false,
59+
tooltip:null,
5860
};
5961
}
6062
}
6163

6264
LeafletLayerModel.serializers={
6365
...WidgetModel.serializers,
6466
popup:{deserialize:unpack_models},
67+
tooltip:{deserialize:unpack_models},
6568
subitems:{deserialize:unpack_models},
6669
};
6770

@@ -83,13 +86,16 @@ export class LeafletLayerView extends LeafletWidgetView {
8386
obj:Layer;
8487
subitems:WidgetModel[];
8588
pWidget:IMessageHandler;
89+
tooltip_content:LeafletLayerView;
90+
tooltip_content_promise:Promise<void>;
8691

8792
create_obj():void{}
8893

8994
initialize(parameters:WidgetView.IInitializeParameters<LeafletLayerModel>){
9095
super.initialize(parameters);
9196
this.map_view=this.options.map_view;
9297
this.popup_content_promise=Promise.resolve();
98+
this.tooltip_content_promise=Promise.resolve();
9399
}
94100

95101
remove_subitem_view(child_view:LeafletLayerView){
@@ -128,6 +134,7 @@ export class LeafletLayerView extends LeafletWidgetView {
128134
this.listenTo(this.model,'change:popup',(model,value_2)=>{
129135
this.bind_popup(value_2);
130136
});
137+
this.bind_tooltip(this.model.get('tooltip'));
131138
this.update_pane();
132139
this.subitem_views=newViewList(
133140
this.add_subitem_model,
@@ -200,6 +207,9 @@ export class LeafletLayerView extends LeafletWidgetView {
200207
this.listenTo(this.model,'change:subitems',()=>{
201208
this.subitem_views.update(this.subitems);
202209
});
210+
this.listenTo(this.model,'change:tooltip',()=>{
211+
this.bind_tooltip(this.model.get('tooltip'));
212+
});
203213
}
204214

205215
remove(){
@@ -210,6 +220,11 @@ export class LeafletLayerView extends LeafletWidgetView {
210220
this.popup_content.remove();
211221
}
212222
});
223+
this.tooltip_content_promise.then(()=>{
224+
if(this.tooltip_content){
225+
this.tooltip_content.remove();
226+
}
227+
});
213228
}
214229

215230
bind_popup(value:WidgetModel){
@@ -252,6 +267,27 @@ export class LeafletLayerView extends LeafletWidgetView {
252267
this.obj.togglePopup();
253268
this.obj.togglePopup();
254269
}
270+
271+
bind_tooltip(value:WidgetModel){
272+
if(this.tooltip_content){
273+
this.obj.unbindTooltip();
274+
this.tooltip_content.remove();
275+
}
276+
if(value){
277+
this.tooltip_content_promise=this.tooltip_content_promise.then(
278+
async()=>{
279+
constview=awaitthis.create_child_view<LeafletLayerView>(value,{
280+
map_view:this.map_view,
281+
});
282+
if(view.objinstanceofTooltip){
283+
this.obj.bindTooltip(view.obj);
284+
}
285+
this.tooltip_content=view;
286+
}
287+
);
288+
}
289+
returnthis.tooltip_content_promise;
290+
}
255291
}
256292

257293
exportclassLeafletUILayerViewextendsLeafletLayerView{}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import{WidgetView}from'@jupyter-widgets/base';
5+
import{Tooltip,TooltipOptions}from'leaflet';
6+
importLfrom'../leaflet';
7+
import{
8+
ILeafletLayerModel,
9+
LeafletUILayerModel,
10+
LeafletUILayerView,
11+
}from'./Layer';
12+
13+
interfaceILeafletTooltipModelextendsILeafletLayerModel{
14+
_view_name:string;
15+
_model_name:string;
16+
location:number[]|null;
17+
}
18+
19+
exportclassLeafletTooltipModelextendsLeafletUILayerModel{
20+
defaults():ILeafletTooltipModel{
21+
return{
22+
...super.defaults(),
23+
_view_name:'LeafletMarkerView',
24+
_model_name:'LeafletMarkerModel',
25+
location:null,
26+
};
27+
}
28+
}
29+
30+
exportclassLeafletTooltipViewextendsLeafletUILayerView{
31+
obj:Tooltip;
32+
33+
initialize(
34+
parameters:WidgetView.IInitializeParameters<LeafletTooltipModel>
35+
){
36+
super.initialize(parameters);
37+
}
38+
39+
create_obj(){
40+
if(this.model.get('location')){
41+
// Stand-alone tooltip
42+
this.obj=(L.tooltipasany)(
43+
this.model.get('location'),
44+
this.get_options()asTooltipOptions
45+
);
46+
}else{
47+
this.obj=L.tooltip(this.get_options()asTooltipOptions);
48+
}
49+
}
50+
51+
model_events(){
52+
super.model_events();
53+
this.listenTo(this.model,'change:location',()=>{
54+
if(this.model.get('location')){
55+
this.obj.setLatLng(this.model.get('location'));
56+
this.send({
57+
event:'move',
58+
location:this.model.get('location'),
59+
});
60+
}
61+
});
62+
this.listenTo(this.model,'change:content',()=>{
63+
this.obj.setContent(this.model.get('content'));
64+
});
65+
}
66+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp