Comment placer précisément un élément div sur une carte à l'aide de la brochure js?

J'ai essayé de plusieurs façons, mais je n'ai pas pu le faire fonctionner. Je veux placer des horloges en haut de la carte dans plusieurs fuseaux horaires. J'ai le javascript pour créer l'horloge et je place l'horloge dans un élément div .

Voici ce que j'ai essayé:

  1. Créez un point avec des coordonnées 0,0 .
  2. À partir de ce point, obtenez la valeur de latitude pour le haut de la carte à l'aide de containerPointToLatLng .
  3. Créez LatLng utilisant le lat ci-dessus et long pour le fuseau horaire.
  4. Convertit ce LatLng en point puis positionne l'élément div avec x,y partir de ce point.

J'exécute la logique à la fois lorsque la page est d'abord rendue, puis sur le redimensionnement du corps. Toutefois, si je change la taille de la fenêtre du navigateur, l'horloge ne se positionne pas correctement.

Aucune suggestion?

Pour répondre à la question précise de OP, c.-à-d. Comment réinstaller l'horloge lorsque la fenêtre du navigateur est redimensionnée (les dimensions du conteneur de la carte peuvent donc avoir changé), on devrait probablement simplement recalculer la position de l'horloge sur l'événement "resize" la carte.

Cependant, il n'est pas clair si OP a placé l'horloge comme un enfant du conteneur de carte, ou ailleurs sur l'arbre DOM de la page.

Il est probablement beaucoup plus facile de le placer comme un enfant de la carte, de sorte que sa position est toujours relative au conteneur de carte.

Quel OP a demandé à l'origine?

Si je comprends correctement le résultat souhaité, l'OP souhaiterait superposer une horloge (ou n'importe quelle information) sur une position géographique particulière (ville de Toronto dans ce cas [UTC -5], selon les commentaires).

Cependant, le conteneur d'information ne doit pas se positionner sur une position fixe de base, c'est-à-dire pas sur un point coordonné géographique précis (comme un marqueur ou une popup), mais en haut du conteneur de carte, de manière similaire à un Contrôle (donc la réponse initiale d'iH8 ).

Sauf qu'il ne doit pas être totalement réparé dans le conteneur de la carte, mais se déplacer horizontalement avec la ville (ou toutes les coordonnées géographiques spécifiées). D'où le commentaire de OP à la réponse d'iH8.

Par conséquent, cela ressemble à quelque chose de similaire à ce site , sauf avec une carte interactive (navigable) et l'en-tête "UTC-5" remplacé par une horloge (ou n'importe quelle information, donc un conteneur HTML devrait le faire) et horizontalement à Toronto.

En d'autres termes, l'horloge devrait s'asseoir à une ligne verticale particulière, c'est-à-dire à la longitude / au méridien .

Malheureusement, même 2 ans et demi après la publication de la question, il n'y a pas encore de plugin Leaflet qui offre de telles fonctionnalités (au moins dans la page Plugins de brochures ).

Extension du cas d'utilisation à une carte fortement agrandie …

Cela étant dit, et compte tenu du fait que l'utilisateur pourrait être en mesure de zoomer fortement dans la ville (OP n'a pas spécifié le niveau de zoom maximal), il se peut que ce soit une très bonne expérience de l'utilisateur si cette horloge suit horizontalement une longitude précise: pour Par exemple, il pourrait suivre le centre-ville de Toronto / l'hôtel de ville ou quel que soit l'endroit particulier, et lorsque l'utilisateur est zoomé dans un autre quartier de la ville, l'horloge n'est plus visible, alors qu'il / elle voit encore une partie de la ville de Toronto …

Pour étendre ce cas d'utilisation, l'horloge devrait très probablement être visible dans n'importe quelle zone qu'elle applique, c'est-à-dire dès que le port de vue de carte coupe le fuseau horaire associé.

Extension du cas d'utilisation à la carte fortement zoomée …

Un autre point non détaillé par OP, est ce qu'il faut faire lorsque des zones de différents fuseaux horaires sont visibles dans le port de vue de carte? Dans le site mentionné ci-dessus , nous avons un en-tête par fuseau horaire visible , ce qui semble être l'information la plus complète que nous puissions obtenir.

Mais puisque Leaflet permet de faire un zoom arrière au niveau 0, où le monde entier (c'est-à-dire essentiellement 24 fuseaux horaires / en fait 39, selon Wikipédia , sans compter l'effet potentiel de l'heure d'été – DST) est représenté avec une largeur de 256 pixels, il y a Peu de place pour s'adapter à toutes ces horloges, si chacun doit être aligné verticalement avec son fuseau horaire associé.

Pour l'instant, supposons que nous ne nous soucions pas si les horloges se chevauchent.

Un cas encore plus personnalisé …

Mais OP peut avoir souhaité afficher l'horloge uniquement pour des endroits particuliers, pas pour le monde entier. OP n'a même pas dit que les horloges seraient différentes (nous pourrions avoir des horloges pour les villes dans le même fuseau horaire, même si cela pourrait être plus intéressant d'avoir ces horloges assises à côté de leur ville, même si elles correspondent à leur latitude, de sorte que Est plus facile de repérer à quelle ville l'horloge est associée, comme dans le cas de 2 villes sur le même méridien, mais dans ce cas, un marqueur avec L.divIcon suffirait).

Par conséquent, un cas personnalisé serait de ne pas tenir compte des fuseaux horaires officiels, mais des zones spécifiées par les développeurs .

Nous oublions donc la latitude et essayons d'aligner une horloge verticalement au-dessus de la zone, tant qu'elle intersecte le port de la vue de la carte.

Décrire une solution générique

Par conséquent, il semble qu'une solution générique soit de permettre au développeur d'applications de spécifier un tableau d'éléments HTML, chacun associé à une gamme de longitudes (pourrait également être une zone / un polygone).

Le cas d'utilisation des fuseaux horaires serait alors un cas particulier où les zones spécifiées sont simplement celles des fuseaux horaires.

Ensuite, chaque élément doit être visible si et seulement si sa zone associée coupe le port de vue (donc, nous introduisons une possibilité de le cacher lorsque la plage de latitude est hors de vue).

En ce qui concerne le positionnement, choisissons:

  • En haut du conteneur de carte (similaire à un contrôle), comme mentionné par OP.
  • Horizontalement centrée dans l'intersection du port de vue et de la zone associée.

HTML:

 <div id="map"></div> <div id="clockToronto" class="clock leaflet-control">Clock here for Toronto</div> <div id="clockBurlington" class="clock leaflet-control">Clock here for Burlington</div> 

CSS:

 .clock { width: 150px; text-align: center; position: absolute; border: 1px solid black; } #clockToronto { background-color: yellow; } #clockBurlington { background-color: orange; } 

JavaScript:

 var map = L.map("map").setView([43.7, -79.4], 10); // Application specific. var clockTorontoElement = L.DomUtil.get("clockToronto"), clockBurlingtonElement = L.DomUtil.get("clockBurlington"), zones = [ { element: clockTorontoElement, // Using the HTML Element for now. width: parseInt(window.getComputedStyle(clockTorontoElement, null).getPropertyValue("width"), 10), area: L.latLngBounds([43.58, -79.64], [43.86, -79.10]) // Using L.latLngBounds for now. }, { element: clockBurlingtonElement, // Using the HTML Element for now. width: parseInt(window.getComputedStyle(clockBurlingtonElement, null).getPropertyValue("width"), 10), area: L.latLngBounds([43.28, -79.96], [43.48, -79.71]) // Using L.latLngBounds for now. } ]; // Initialization var controlsContainer = map._container.getElementsByClassName("leaflet-control-container")[0], firstCorner = controlsContainer.firstChild, mapContainerWidth; map.on("resize", setMapContainerWidth); setMapContainerWidth(); // Applying the zones. for (var i = 0; i < zones.length; i += 1) { setZone(zones[i]); } function setZone(zoneData) { // Visualize the area. L.rectangle(zoneData.area).addTo(map); console.log("width: " + zoneData.width); controlsContainer.insertBefore(zoneData.element, firstCorner); map.on("move resize", function () { updateZone(zoneData); }); updateZone(zoneData); } function updateZone(zoneData) { var mapBounds = map.getBounds(), zoneArea = zoneData.area, style = zoneData.element.style; if (mapBounds.intersects(zoneArea)) { style.display = "block"; var hcenterLng = getIntersectionHorizontalCenter(mapBounds, zoneArea), hcenter = isNaN(hcenterLng) ? 0 : map.latLngToContainerPoint([0, hcenterLng]).x; // Update Element position. // Could be refined to keep the entire Element visible, rather than cropping it. style.left = (hcenter - (zoneData.width / 2)) + "px"; } else { style.display = "none"; } } function getIntersectionHorizontalCenter(bounds1, bounds2) { var west1 = bounds1.getWest(), west2 = bounds2.getWest(), westIn = west1 < west2 ? west2 : west1, east1 = bounds1.getEast(), east2 = bounds2.getEast(), eastIn = east1 < east2 ? east1 : east2; return (westIn + eastIn) / 2; } function setMapContainerWidth() { mapContainerWidth = map.getSize().x; } 

Entrez la description de l'image ici

Démo en direct: http://plnkr.co/edit/V2pvcva5S9OZ2N7LlI8r?p=preview

Généralement, on utiliserait L.Control pour créer un contrôle personnalisé que vous pouvez ensuite ajouter à la couche de contrôle. Si vous le faites, le dépliant prend en charge le positionnement lors du redimensionnement de la carte. Jetez un oeil à la référence pour L.Control: http://leafletjs.com/reference.html#control

Il existe un exemple de contrôle personnalisé dans la référence: http://leafletjs.com/reference.html#icontrol Si vous souhaitez plus d'exemples, vous pouvez consulter l'un des nombreux plugins de contrôle personnalisés pour voir comment ils ont implémenté L .Control: http://leafletjs.com/plugins.html (sous Contrôles et interaction)

Le seul inconvénient de L.Control est que vous ne pouvez pas positionner un contrôle verticalement ou horizontalement centrée. Vous ne pouvez utiliser que de manière excessive, verticale, inférieure et inférieure.