1616except ImportError :
1717 dl = None
1818
19+ # Max zoom of default Leaflet tile layer
20+ LEAFLET_DEFAULT_MAX_ZOOM = 18
21+
22+ # Empirically-determined max zoom values for Cytoscape
23+ # which correspond to max zoom values of Leaflet
24+ LEAF_TO_CYTO_MAX_ZOOM_MAPPING = {
25+ 16 : 0.418 ,
26+ 17 : 0.837 ,
27+ 18 : 1.674 ,
28+ 19 : 3.349 ,
29+ 20 : 6.698 ,
30+ 21 : 13.396 ,
31+ 22 : 26.793 ,
32+ }
33+
1934
2035class CyLeaflet (html .Div ):
2136 def __init__ (
@@ -25,6 +40,7 @@ def __init__(
2540 leaflet_props = None ,
2641 width = "600px" ,
2742 height = "480px" ,
43+ max_zoom = None ,
2844 ):
2945 # Throw error if `dash_leaflet` package is not installed
3046 if dl is None :
@@ -42,7 +58,7 @@ def __init__(
4258 leaflet_props = leaflet_props or {}
4359 elements = cytoscape_props .get ("elements" , [])
4460 cytoscape_props , leaflet_props = self .set_default_props_and_overrides (
45- cytoscape_props , leaflet_props
61+ cytoscape_props , leaflet_props , max_zoom
4662 )
4763
4864 super ().__init__ (
@@ -84,7 +100,14 @@ def __init__(
84100 },
85101 )
86102
87- def set_default_props_and_overrides (self , user_cytoscape_props , user_leaflet_props ):
103+ def set_default_props_and_overrides (
104+ self , user_cytoscape_props , user_leaflet_props , max_zoom
105+ ):
106+ # Try to figure out Leaflet maxZoom from Leaflet children,
107+ # then convert to Cytoscape max zoom
108+ leaflet_max_zoom = max_zoom or self .get_leaflet_max_zoom (user_leaflet_props )
109+ cytoscape_max_zoom = self .get_cytoscape_max_zoom (leaflet_max_zoom )
110+
88111 # Props where we want to override values supplied by the user
89112 # These are props which are required for CyLeaflet to work properly
90113 cytoscape_overrides = {
@@ -113,7 +136,7 @@ def set_default_props_and_overrides(self, user_cytoscape_props, user_leaflet_pro
113136 # if a value is not supplied by the user
114137 cytoscape_defaults = {
115138 "boxSelectionEnabled" : True ,
116- "maxZoom" : 1.67 ,
139+ "maxZoom" : cytoscape_max_zoom ,
117140 }
118141 leaflet_defaults = {
119142 "children" : dl .TileLayer (),
@@ -133,6 +156,37 @@ def set_default_props_and_overrides(self, user_cytoscape_props, user_leaflet_pro
133156
134157 return cytoscape_props , leaflet_props
135158
159+ # Try to figure out Leaflet maxZoom from Leaflet children
160+ # If not possible, return the maxZoom of the default Leaflet tile layer
161+ def get_leaflet_max_zoom (self , user_leaflet_props ):
162+ if "children" not in user_leaflet_props or user_leaflet_props ["children" ] == []:
163+ return LEAFLET_DEFAULT_MAX_ZOOM
164+
165+ if isinstance (user_leaflet_props ["children" ], list ):
166+ leaflet_children = user_leaflet_props ["children" ]
167+ else :
168+ leaflet_children = [user_leaflet_props ["children" ]]
169+
170+ max_zooms = [
171+ c .maxZoom
172+ for c in leaflet_children
173+ if isinstance (c , dl .TileLayer ) and hasattr (c , "maxZoom" )
174+ ]
175+
176+ return max_zooms [0 ] if max_zooms else LEAFLET_DEFAULT_MAX_ZOOM
177+
178+ # Given a maxZoom value for Leaflet, map it to the corresponding maxZoom value for Cytoscape
179+ # If the value is out of range, return the closest value
180+ def get_cytoscape_max_zoom (self , leaflet_max_zoom ):
181+ leaflet_max_zoom = leaflet_max_zoom or 0
182+ leaflet_max_zoom = min (
183+ leaflet_max_zoom , max (LEAF_TO_CYTO_MAX_ZOOM_MAPPING .keys ())
184+ )
185+ leaflet_max_zoom = max (
186+ leaflet_max_zoom , min (LEAF_TO_CYTO_MAX_ZOOM_MAPPING .keys ())
187+ )
188+ return LEAF_TO_CYTO_MAX_ZOOM_MAPPING [leaflet_max_zoom ]
189+
136190
137191if dl is not None :
138192 clientside_callback (
0 commit comments