You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.7 KiB

4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
  1. import { Controller } from '@hotwired/stimulus';
  2. import 'leaflet';
  3. export default class extends Controller {
  4. static values = {
  5. geojson: String,
  6. overpassResult: String,
  7. icon: String,
  8. popupUrl: String,
  9. }
  10. connect() {
  11. const simpleIcon = L.icon({
  12. iconUrl: this.iconValue,
  13. iconSize: [16, 16],
  14. iconAnchor: [8, 16],
  15. popupAnchor: [0, 0],
  16. });
  17. const iconHtml = `
  18. <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="bi bi-geo-alt-fill" viewBox="0 0 16 16">
  19. <path fill="currentColor" d="M8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10m0-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6"/>
  20. </svg>
  21. `;
  22. const icons = {
  23. 'danger': L.divIcon({ html: iconHtml, className: 'svg-icon text-danger', iconSize: [16, 16], iconAnchor: [8, 16], }),
  24. 'warning': L.divIcon({ html: iconHtml, className: 'svg-icon text-warning', iconSize: [16, 16], iconAnchor: [8, 16], }),
  25. 'success': L.divIcon({ html: iconHtml, className: 'svg-icon text-success', iconSize: [16, 16], iconAnchor: [8, 16], }),
  26. 'info': L.divIcon({ html: iconHtml, className: 'svg-icon text-info', iconSize: [16, 16], iconAnchor: [8, 16], }),
  27. };
  28. var geojsons, _this = this, map = L.map(this.element);
  29. L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
  30. maxZoom: 19,
  31. attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
  32. }).addTo(map);
  33. var layer = L.featureGroup();
  34. var layer2 = L.featureGroup();
  35. if (this.overpassResultValue !== '') {
  36. geojsons = JSON.parse(this.overpassResultValue);
  37. if (geojsons.elements.length > 0) {
  38. geojsons.elements.forEach(function (element) {
  39. element.members.forEach(function (member) {
  40. const polygon = L.polyline(member.geometry.map(function (coord) { return L.latLng(coord.lat, coord.lon)}), {
  41. color: '#0dcaf0',
  42. weight: 6,
  43. opacity: 0.8,
  44. }).addTo(layer2).bindPopup(L.popup({
  45. overpassElement: element,
  46. }).setContent('…'));
  47. });
  48. });
  49. layer2.on('popupopen', function (event) {
  50. var element = event.popup.options.overpassElement;
  51. delete element.members;
  52. element['map'] = {
  53. 'center': map.getCenter(),
  54. 'zoom': map.getZoom(),
  55. };
  56. fetch(_this.popupUrlValue + '?' + (new URLSearchParams({
  57. 'element': JSON.stringify(element),
  58. })))
  59. .then(function (response) {
  60. return response.text();
  61. })
  62. .then(function (text) {
  63. event.popup.setContent(text);
  64. });
  65. });
  66. layer2.addTo(layer);
  67. }
  68. }
  69. var layer1 = L.featureGroup();
  70. geojsons = JSON.parse(this.geojsonValue);
  71. if (geojsons.length > 0) {
  72. geojsons.forEach(function (geojson) {
  73. const feature0 = geojson.features[0].properties;
  74. const polygon = L.geoJSON(geojson, {
  75. style: function (feature) {
  76. var color = 'blue';
  77. switch (feature.properties.color) {
  78. case 'danger' : color = '#dc3545'; break
  79. case 'warning' : color = '#ffc107'; break
  80. case 'success' : color = '#198754'; break
  81. }
  82. return {color: color};
  83. }
  84. }).bindTooltip(feature0.name).addTo(layer1).on('click', function (event) {
  85. window.location.href = event.layer.feature.properties.url;
  86. });
  87. L.marker(polygon.getBounds().getCenter(), {
  88. icon: icons[feature0.color],
  89. title: feature0.name,
  90. clickUrl: feature0.url,
  91. }).addTo(layer1).on('click', function (event) {
  92. window.location.href = event.target.options.clickUrl;
  93. });
  94. });
  95. layer1.addTo(layer);
  96. }
  97. layer.addTo(map);
  98. if (this.overpassResultValue !== '') {
  99. L.control.layers({}, {
  100. 'Overpass': layer2,
  101. 'Tâches': layer1,
  102. }).addTo(map);
  103. }
  104. map.fitBounds(layer1.getBounds());
  105. }
  106. }