Skip to content

Instantly share code, notes, and snippets.

@frogcat
Created July 12, 2018 10:55
Show Gist options
  • Save frogcat/9d3090717cb6b1a17cd807d2baa4037c to your computer and use it in GitHub Desktop.
Save frogcat/9d3090717cb6b1a17cd807d2baa4037c to your computer and use it in GitHub Desktop.
leaflet marker with leadline

leaflet marker with leadline

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>leaflet marker with leadline</title>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/[email protected]/leaflet-hash.js"></script>
<style>
.my-leaflet-div-icon {
width: auto !important;
padding: 2px;
background: orange;
color: black;
border: 1px solid black;
font-weight: bold;
white-space: nowrap;
}
</style>
<script>
var MyMarker = L.FeatureGroup.extend({
initialize: function(latlng, caption) {
this.latlng = latlng;
this.circle = L.circleMarker(latlng, {
radius: 5,
fillColor: "black",
fill: true,
stroke: false,
fillOpacity: 1.0
});
this.caption = L.marker(latlng, {
icon: L.divIcon({
"html": caption,
"className": "my-leaflet-div-icon"
})
});
this.line = L.polyline([], {
color: "black"
});
L.FeatureGroup.prototype.initialize.call(this, [
this.circle, this.caption, this.line
]);
},
update: function(nodes, links) {
if (!this._map) return;
if (!this._map.getBounds().contains(this.latlng)) return;
var xy = this._map.latLngToContainerPoint(this.latlng);
nodes.push({
x: xy.x,
y: xy.y,
fx: xy.x,
fy: xy.y
});
nodes.push({
x: xy.x + 20,
y: xy.y - 20,
target: this
});
links.push({
source: nodes[nodes.length - 2],
target: nodes[nodes.length - 1]
});
},
updatePosition: function(data) {
var p = this.circle.getLatLng();
var q = this._map.containerPointToLatLng(data);
this.caption.setLatLng(q);
this.line.setLatLngs([p, q]);
}
});
</script>
</head>
<body>
<div id="map" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
<script>
var map = L.map("map", L.extend({
zoom: 14,
maxZoom: 22,
center: [35.6059,139.6296]
}, L.Hash.parseHash(location.hash)));
map.zoomControl.setPosition("bottomright");
L.hash(map);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().distance(10))
.force("charge", d3.forceCollide(20))
.on("tick", function() {
this.nodes().forEach(function(a) {
if (a.target) a.target.updatePosition(a);
});
});
map.on("movestart zoomstart", function() {
simulation.stop();
}).on("moveend zoomend", function() {
var nodes = [];
var links = [];
map.eachLayer(function(layer) {
if (layer instanceof MyMarker) layer.update(nodes, links);
});
simulation.nodes(nodes).force("link").links(links);
simulation.alpha(0.5).restart();
}).fire("moveend");
L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg", {
attribution: "地理院タイル"
}).addTo(map);
L.tileLayer(L.Util.emptyImageUrl, {
maxNativeZoom: 10,
maxZoom: 18,
minNativeZoom: 10,
attribution: "地理院タイル"
}).on("tileloadstart", function(e) {
var url = L.Util.template("https://cyberjapandata.gsi.go.jp/xyz/skhb01/{z}/{x}/{y}.geojson", e.coords);
fetch(url).then(a => a.ok ? a.json() : null).then(a => {
(a ? a.features : []).forEach(f => {
new MyMarker(L.latLng(f.geometry.coordinates[1], f.geometry.coordinates[0]), f.properties.name).addTo(map);
});
map.fire("moveend");
});
}).addTo(map);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment