leaflet_documentation.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. from nicegui import ui
  2. from . import doc
  3. @doc.demo(ui.leaflet)
  4. def main_demo() -> None:
  5. m = ui.leaflet(center=(51.505, -0.09))
  6. ui.label().bind_text_from(m, 'center', lambda center: f'Center: {center[0]:.3f}, {center[1]:.3f}')
  7. ui.label().bind_text_from(m, 'zoom', lambda zoom: f'Zoom: {zoom}')
  8. with ui.grid(columns=2):
  9. ui.button('London', on_click=lambda: m.set_center((51.505, -0.090)))
  10. ui.button('Berlin', on_click=lambda: m.set_center((52.520, 13.405)))
  11. ui.button(icon='zoom_in', on_click=lambda: m.set_zoom(m.zoom + 1))
  12. ui.button(icon='zoom_out', on_click=lambda: m.set_zoom(m.zoom - 1))
  13. @doc.demo('Changing the Map Style', '''
  14. The default map style is OpenStreetMap.
  15. You can find more map styles at <https://leaflet-extras.github.io/leaflet-providers/preview/>.
  16. Each call to `tile_layer` stacks upon the previous ones.
  17. So if you want to change the map style, you have to remove the default one first.
  18. *Updated in version 2.12.0: Both WMTS and WMS map services are supported.*
  19. ''')
  20. def map_style() -> None:
  21. ui.label('Web Map Tile Service')
  22. map1 = ui.leaflet(center=(51.505, -0.090), zoom=3)
  23. map1.clear_layers()
  24. map1.tile_layer(
  25. url_template=r'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
  26. options={
  27. 'maxZoom': 17,
  28. 'attribution':
  29. 'Map data: &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="https://viewfinderpanoramas.org/">SRTM</a> | '
  30. 'Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'
  31. },
  32. )
  33. ui.label('Web Map Service')
  34. map2 = ui.leaflet(center=(51.505, -0.090), zoom=3)
  35. map2.clear_layers()
  36. map2.wms_layer(
  37. url_template='http://ows.mundialis.de/services/service?',
  38. options={
  39. 'layers': 'TOPO-WMS,OSM-Overlay-WMS'
  40. },
  41. )
  42. @doc.demo('Add Markers on Click', '''
  43. You can add markers to the map with `marker`.
  44. The `center` argument is a tuple of latitude and longitude.
  45. This demo adds markers by clicking on the map.
  46. Note that the "map-click" event refers to the click event of the map object,
  47. while the "click" event refers to the click event of the container div.
  48. ''')
  49. def markers() -> None:
  50. from nicegui import events
  51. m = ui.leaflet(center=(51.505, -0.09))
  52. def handle_click(e: events.GenericEventArguments):
  53. lat = e.args['latlng']['lat']
  54. lng = e.args['latlng']['lng']
  55. m.marker(latlng=(lat, lng))
  56. m.on('map-click', handle_click)
  57. @doc.demo('Move Markers', '''
  58. You can move markers with the `move` method.
  59. ''')
  60. def move_markers() -> None:
  61. m = ui.leaflet(center=(51.505, -0.09))
  62. marker = m.marker(latlng=m.center)
  63. ui.button('Move marker', on_click=lambda: marker.move(51.51, -0.09))
  64. @doc.demo('Image Overlays', '''
  65. Leaflet supports [image overlays](https://leafletjs.com/reference.html#imageoverlay).
  66. You can add an image overlay with the `image_overlay` method.
  67. *Added in version 2.17.0*
  68. ''')
  69. def overlay_image():
  70. m = ui.leaflet(center=(40.74, -74.18), zoom=11)
  71. m.image_overlay(
  72. url='https://maps.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
  73. bounds=[[40.712216, -74.22655], [40.773941, -74.12544]],
  74. options={'opacity': 0.8},
  75. )
  76. @doc.demo('Video Overlays', '''
  77. Leaflet supports [video overlays](https://leafletjs.com/reference.html#videooverlay).
  78. You can add a video overlay with the `video_overlay` method.
  79. *Added in version 2.17.0*
  80. ''')
  81. def overlay_video():
  82. m = ui.leaflet(center=(23.0, -115.0), zoom=3)
  83. m.video_overlay(
  84. url='https://www.mapbox.com/bites/00188/patricia_nasa.webm',
  85. bounds=[[32, -130], [13, -100]],
  86. options={'opacity': 0.8, 'autoplay': True, 'playsInline': True},
  87. )
  88. @doc.demo('Vector Layers', '''
  89. Leaflet supports a set of [vector layers](https://leafletjs.com/reference.html#:~:text=VideoOverlay-,Vector%20Layers,-Path) like circle, polygon etc.
  90. These can be added with the `generic_layer` method.
  91. We are happy to review any pull requests to add more specific layers to simplify usage.
  92. ''')
  93. def vector_layers() -> None:
  94. m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
  95. m.generic_layer(name='circle', args=[m.center, {'color': 'red', 'radius': 300}])
  96. @doc.demo('Disable Pan and Zoom', '''
  97. There are [several options to configure the map in Leaflet](https://leafletjs.com/reference.html#map).
  98. This demo disables the pan and zoom controls.
  99. ''')
  100. def disable_pan_zoom() -> None:
  101. options = {
  102. 'zoomControl': False,
  103. 'scrollWheelZoom': False,
  104. 'doubleClickZoom': False,
  105. 'boxZoom': False,
  106. 'keyboard': False,
  107. 'dragging': False,
  108. }
  109. ui.leaflet(center=(51.505, -0.09), options=options)
  110. @doc.demo('Draw on Map', '''
  111. You can enable a toolbar to draw on the map.
  112. The `draw_control` can be used to configure the toolbar.
  113. This demo adds markers and polygons by clicking on the map.
  114. By setting "edit" and "remove" to `True` (the default), you can enable editing and deleting drawn shapes.
  115. ''')
  116. def draw_on_map() -> None:
  117. from nicegui import events
  118. def handle_draw(e: events.GenericEventArguments):
  119. layer_type = e.args['layerType']
  120. coords = e.args['layer'].get('_latlng') or e.args['layer'].get('_latlngs')
  121. ui.notify(f'Drawn a {layer_type} at {coords}')
  122. draw_control = {
  123. 'draw': {
  124. 'polygon': True,
  125. 'marker': True,
  126. 'circle': True,
  127. 'rectangle': True,
  128. 'polyline': True,
  129. 'circlemarker': True,
  130. },
  131. 'edit': {
  132. 'edit': True,
  133. 'remove': True,
  134. },
  135. }
  136. m = ui.leaflet(center=(51.505, -0.09), draw_control=draw_control)
  137. m.classes('h-96')
  138. m.on('draw:created', handle_draw)
  139. m.on('draw:edited', lambda: ui.notify('Edit completed'))
  140. m.on('draw:deleted', lambda: ui.notify('Delete completed'))
  141. @doc.demo('Draw with Custom Options', '''
  142. You can draw shapes with custom options like stroke color and weight.
  143. To hide the default rendering of drawn items, set `hide_drawn_items` to `True`.
  144. ''')
  145. def draw_custom_options():
  146. from nicegui import events
  147. def handle_draw(e: events.GenericEventArguments):
  148. options = {'color': 'red', 'weight': 1}
  149. m.generic_layer(name='polygon', args=[e.args['layer']['_latlngs'], options])
  150. draw_control = {
  151. 'draw': {
  152. 'polygon': True,
  153. 'marker': False,
  154. 'circle': False,
  155. 'rectangle': False,
  156. 'polyline': False,
  157. 'circlemarker': False,
  158. },
  159. 'edit': {
  160. 'edit': False,
  161. 'remove': False,
  162. },
  163. }
  164. m = ui.leaflet(center=(51.5, 0), draw_control=draw_control, hide_drawn_items=True)
  165. m.on('draw:created', handle_draw)
  166. @doc.demo('Run Map Methods', '''
  167. You can run methods of the Leaflet map object with `run_map_method`.
  168. This demo shows how to fit the map to the whole world.
  169. ''')
  170. def run_map_methods() -> None:
  171. m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
  172. ui.button('Fit world', on_click=lambda: m.run_map_method('fitWorld'))
  173. @doc.demo('Run Layer Methods', '''
  174. You can run methods of the Leaflet layer objects with `run_layer_method`.
  175. This demo shows how to change the opacity of a marker or change its icon.
  176. ''')
  177. def run_layer_methods() -> None:
  178. m = ui.leaflet(center=(51.505, -0.09)).classes('h-32')
  179. marker = m.marker(latlng=m.center)
  180. ui.button('Hide', on_click=lambda: marker.run_method('setOpacity', 0.3))
  181. ui.button('Show', on_click=lambda: marker.run_method('setOpacity', 1.0))
  182. icon = 'L.icon({iconUrl: "https://leafletjs.com/examples/custom-icons/leaf-green.png"})'
  183. ui.button('Change icon', on_click=lambda: marker.run_method(':setIcon', icon))
  184. @doc.demo('Wait for Initialization', '''
  185. You can wait for the map to be initialized with the `initialized` method.
  186. This is necessary when you want to run methods like fitting the bounds of the map right after the map is created.
  187. ''')
  188. async def wait_for_init() -> None:
  189. # @ui.page('/')
  190. async def page():
  191. m = ui.leaflet(zoom=5)
  192. central_park = m.generic_layer(name='polygon', args=[[
  193. (40.767809, -73.981249),
  194. (40.800273, -73.958291),
  195. (40.797011, -73.949683),
  196. (40.764704, -73.973741),
  197. ]])
  198. await m.initialized()
  199. bounds = await central_park.run_method('getBounds')
  200. m.run_map_method('fitBounds', [[bounds['_southWest'], bounds['_northEast']]])
  201. ui.timer(0, page, once=True) # HIDE
  202. @doc.demo('Leaflet Plugins', '''
  203. You can add plugins to the map by passing the URLs of JS and CSS files to the `additional_resources` parameter.
  204. This demo shows how to add the [Leaflet.RotatedMarker](https://github.com/bbecquet/Leaflet.RotatedMarker) plugin.
  205. It allows you to rotate markers by a given `rotationAngle`.
  206. *Added in version 2.11.0*
  207. ''')
  208. def leaflet_plugins() -> None:
  209. m = ui.leaflet((51.51, -0.09), additional_resources=[
  210. 'https://unpkg.com/leaflet-rotatedmarker@0.2.0/leaflet.rotatedMarker.js',
  211. ])
  212. m.marker(latlng=(51.51, -0.091), options={'rotationAngle': -30})
  213. m.marker(latlng=(51.51, -0.090), options={'rotationAngle': 30})
  214. doc.reference(ui.leaflet)