132 lines
4.4 KiB
HTML
132 lines
4.4 KiB
HTML
<!DOCTYPE html >
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>mapboxgl.js + d3.js tutorial - 03</title>
|
|
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
|
|
<link href="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet" />
|
|
<script src="https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js"></script>
|
|
<script src="https://d3js.org/d3.v4.min.js"></script>
|
|
<style media="screen">
|
|
body { margin:0; padding:0; }
|
|
#map { position:absolute; top:0; bottom:0; width:100%; }
|
|
svg {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.park-label {
|
|
font-family: Arial, sans-serif;
|
|
font-size: 12px;
|
|
fill: #333;
|
|
text-anchor: middle;
|
|
dominant-baseline: middle;
|
|
pointer-events: none;
|
|
opacity: 0.8;
|
|
}
|
|
.park-icon {
|
|
cursor: pointer;
|
|
transition: 0.3s opacity;
|
|
}
|
|
.park-icon:hover {
|
|
opacity: 1 !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="map">
|
|
</div>
|
|
<script>
|
|
//////////////////
|
|
// Mapbox stuff
|
|
//////////////////
|
|
// Set-up map
|
|
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9yZGl0b3N0IiwiYSI6ImQtcVkyclEifQ.vwKrOGZoZSj3N-9MB6FF_A';
|
|
var map = new mapboxgl.Map({
|
|
container: 'map',
|
|
style: 'mapbox://styles/mapbox/outdoors-v9',
|
|
zoom: 11.5,
|
|
center: [13.4426, 52.5100],
|
|
});
|
|
|
|
//////////////////////////
|
|
// Mapbox+D3 Connection
|
|
//////////////////////////
|
|
// Get Mapbox map canvas container
|
|
var canvas = map.getCanvasContainer();
|
|
// Overlay d3 on the map
|
|
var svg = d3.select(canvas).append("svg");
|
|
|
|
// Load map and dataset
|
|
map.on('load', function () {
|
|
d3.json("data/berlin-parks.json", function(err, data) {
|
|
drawData(data);
|
|
});
|
|
});
|
|
|
|
// Project GeoJSON coordinate to the map's current state
|
|
function project(d) {
|
|
return map.project(new mapboxgl.LngLat(+d[0], +d[1]));
|
|
}
|
|
|
|
//////////////
|
|
// D3 stuff
|
|
//////////////
|
|
// Draw GeoJSON data with d3
|
|
var parkElements;
|
|
function drawData(data) {
|
|
console.log("draw data");
|
|
|
|
// Add icons and labels
|
|
parkElements = svg.selectAll(".park-element")
|
|
.data(data.features)
|
|
.enter()
|
|
.append("g")
|
|
.attr("class", "park-element")
|
|
.attr("transform", function(d) {
|
|
var coord = project(d.geometry.coordinates);
|
|
return "translate(" + coord.x + "," + coord.y + ")";
|
|
})
|
|
.on("click", function(d) {
|
|
alert(d.properties.name);
|
|
});
|
|
|
|
// Add park icon (using a simple SVG path for a tree/leaf)
|
|
parkElements.append("path")
|
|
.attr("class", "park-icon")
|
|
.attr("d", "M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5a2.5 2.5 0 0 1 0-5 2.5 2.5 0 0 1 0 5z")
|
|
.attr("fill", "#4CAF50")
|
|
.attr("stroke", "#388E3C")
|
|
.attr("stroke-width", 1)
|
|
.attr("transform", "scale(0.7)")
|
|
.attr("opacity", 0.9);
|
|
|
|
// Add park name label
|
|
parkElements.append("text")
|
|
.attr("class", "park-label")
|
|
.text(function(d) {
|
|
return d.properties.name || "Unnamed Park";
|
|
})
|
|
.attr("dy", 25); // Position below the icon
|
|
|
|
// Call the update function
|
|
update();
|
|
|
|
// Update on map interaction
|
|
map.on("viewreset", update);
|
|
map.on("move", update);
|
|
map.on("moveend", update);
|
|
}
|
|
|
|
// Update d3 shapes' positions to the map's current state
|
|
function update() {
|
|
console.log("update");
|
|
svg.selectAll(".park-element")
|
|
.attr("transform", function(d) {
|
|
var coord = project(d.geometry.coordinates);
|
|
return "translate(" + coord.x + "," + coord.y + ")";
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |