javascript - Cum să faci ca căile SVG să fie clicabile în Leaflet și să obții ID-ul căii prin click


Sunt nou în programarea cu Leaflet, am un fișier .svg și vreau să-l fac clicabil atunci când este suprapus pe OpenStreetMap.

Am încercat să-l fac ca un suprapus pe o hartă OpenStreetMap folosind opțiunea Image-overlay, dar SVG-ul nu este clicabil.

Practic vreau să obțin ID-ul path-ului sau elementului SVG pe care l-am făcut clic (oricum îl numești) în leaflet. Harta se mărește atunci când dau clic.

var imageUrl = 'test2.svg', 
                imageBounds = [(image bounds)]; 
L.imageOverlay(imageUrl, imageBounds).addTo(map);

Răspuns #1

Încărcarea fișierului SVG

Poți încărca fișierul tău printr-un imageOverlay, dar nu vei primi evenimente pentru căi/grupuri/forme individuale, ești limitat la evenimente asupra suprapunerii.

Pentru a obține evenimente pe componentele SVG-ului, trebuie să îl încorporați în nodurile DOM, fie prin includere directă, fie prin încărcarea acestuia și crearea nodurilor necesare. Ceva de genul acesta 1:

var url = 'https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg';
var req = new XMLHttpRequest();
req.onload = function(resp) {
    var xml = this.responseXML;
    var importedNode = document.importNode(xml.documentElement, true);
    var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
    g.appendChild(importedNode);
    g.setAttribute('class', 'svglayer');

    var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.appendChild(g);
    svg.addEventListener('click', function(e) {
        console.log(e.target.id)
    })

    document.body.appendChild(svg);
};
req.open("GET", url, true);
req.send();

Acest fragment va încărca un fișier SVG, îl va adăuga în DOM și va configura un eveniment click care va înregistra id-ul elementului țintă.

Încorporarea SVG într-o hartă

Înarmat cu această cunoștință, poți adăuga nodul SVG într-un strat de hartă în loc de document.body. Iată un exemplu simplu care modifică direct stratul overlay :

map.getPane('overlayPane').appendChild(svg);

Un punct important de reținut este că Leaflet dezactivează clicurile pe elementele individuale de traseu prin setarea proprietății CSS pointer-events la none. Trebuie să modificați acest lucru pentru a obține evenimente pe nodurile traseului, de aceea este adăugată proprietatea CSS:

.leaflet-pane > svg .svglayer path {
    pointer-events: auto ;
}

Și o demonstrație

var map = L.map(document.getElementById('map'),{
    renderer: L.canvas()
}).setView([48.8583736, 2.2922926], 15);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);


var url = 'https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg';
var req = new XMLHttpRequest();
req.onload = function(resp) {
    var xml = this.responseXML;
    var importedNode = document.importNode(xml.documentElement, true);
    var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
    g.appendChild(importedNode);
    g.setAttribute('class', 'svglayer');

    var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.appendChild(g);
    svg.addEventListener('click', function(e) {
        console.log(e.target.id, e.target.tagName)
    })

    map.getPane('overlayPane').appendChild(svg);
};
req.open("GET", url, true);
req.send();
html, body {padding:0; margin:0; height: 100%}
#map {height: 180px}


.leaflet-pane > svg .svglayer path {
    pointer-events: auto ;
}
<link rel="stylesheet" href="https://unpkg.com/[email /dist/leaflet.css" integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ==" crossorigin=""/>
<script src="https://unpkg.com/[email /dist/leaflet.js" integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log==" crossorigin=""></script>

<div id='map'>

</div>

1 Imagine de la autorii Ghostscript (GPL Ghostscript SVN: tiger.eps) [GPL (http://www.gnu.org/licenses/gpl.html)], prin Wikimedia Commons

Răspunsul #2

Trebuie să specificați în mod explicit opțiunea interactive pe Suprapunerea de Imagine:

Dacă true, suprapunerea imaginii va emite evenimente de mouse atunci când este făcut clic sau când treceți cursorul peste ea.

var map = L.map("map").setView([48.85, 2.35], 12);

var imageBounds = [
  [48.8, 2.3],
  [48.9, 2.4]
];

var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/9/9c/Map_of_country_subdivisions_%28states%29.svg';

var imageOverlay = L.imageOverlay(imageUrl, imageBounds, {
  interactive: true,
  attribution: '<a href="https://commons.wikimedia.org/wiki/File:Map_of_country_subdivisions_(states).svg">CC-BY-SA 4.0 Wikimedia contributor</a>'
}).addTo(map);

imageOverlay.on('click', function(event) {
  alert('clicked on SVG image');
});

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
<link rel="stylesheet" href="https://unpkg.com/[email /dist/leaflet.css">
<script src="https://unpkg.com/[email /dist/leaflet-src.js"></script>

<div id="map" style="height: 200px"></div>