leaflet.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import logging
  2. from typing import Dict, Optional, Tuple, Union
  3. from nicegui import ui
  4. from nicegui.events import ValueChangeEventArguments
  5. class map(ui.card):
  6. def __init__(self):
  7. super().__init__()
  8. self.classes('osm-map').style('width:100%;height:300px;transition:opacity 1s;opacity:0.1')
  9. self.add_leaflet_js()
  10. async def set_location(self, location: Union[Optional[Tuple[float, float]], Dict[str, Tuple[float, float]], ValueChangeEventArguments]):
  11. try:
  12. if isinstance(location, ValueChangeEventArguments):
  13. location = location.value
  14. if isinstance(location, dict):
  15. location = location.get('location', location.get('value', None))
  16. if not isinstance(location, tuple) or len(location) != 2 or not all(
  17. isinstance(x, float) or isinstance(x, int) for x in location):
  18. self.style('opacity: 0.1;')
  19. logging.warning(f'Invalid location: {location}')
  20. return
  21. self.style('opacity: 1;')
  22. await ui.run_javascript(f'''
  23. target = L.latLng("{location[0]}", "{location[1]}")
  24. map.setView(target, 9);
  25. if (marker != undefined) map.removeLayer(marker);
  26. marker = L.marker(target);
  27. marker.addTo(map);
  28. 0 // return something so we do net get a js error
  29. ''')
  30. except:
  31. logging.exception(f'could not update {location}')
  32. @staticmethod
  33. def add_leaflet_js():
  34. ui.add_head_html(r'''
  35. <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
  36. <link href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" rel="stylesheet"/>
  37. <script>
  38. function waitForElm(selector) {
  39. return new Promise(resolve => {
  40. if (document.querySelector(selector)) {
  41. return resolve(document.querySelector(selector));
  42. }
  43. const observer = new MutationObserver(mutations => {
  44. if (document.querySelector(selector)) {
  45. resolve(document.querySelector(selector));
  46. observer.disconnect();
  47. }
  48. });
  49. observer.observe(document.body, {
  50. childList: true,
  51. subtree: true
  52. });
  53. });
  54. }
  55. var marker;
  56. var map;
  57. document.addEventListener("DOMContentLoaded", function() {
  58. waitForElm('.osm-map').then((container) => {
  59. map = L.map(container);
  60. L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  61. attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
  62. }).addTo(map);
  63. });
  64. });
  65. </script>
  66. ''')