Working version

This commit is contained in:
Moises Leos
2025-08-25 08:56:15 -06:00
parent bf5f338960
commit 58aae49391
2 changed files with 147 additions and 9 deletions

View File

@@ -4,8 +4,8 @@
<meta charset="utf-8" />
<title>mapboxgl.js + d3.js tutorial - 02</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.tiles.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">
@@ -54,7 +54,7 @@
// Load map and dataset
map.on('load', function () {
d3.json("data/berlin-parks.json", function(err, data) {
d3.json("data/berlin-parks-new.json", function(err, data) {
drawData(data);
});
});
@@ -71,26 +71,164 @@
// Draw GeoJSON data with d3
var circles;
var labels;
function drawData(data) {
console.log("draw data");
// Add circles
circles = svg.selectAll("circle")
.data(data.features)
.enter()
.append("circle")
.attr("r", 16);
.attr("r", 8);
/*.append("title") // append a title for tooltip
.text(function(d) { return d.properties.name; });*/
// Add labels
/*labels = svg.selectAll("text")
.data(data.features)
.enter()
.append("text")
.text(function(d) { return d.properties.name; }) // or any other property
.attr("font-size", "12px")
.attr("fill", "black")
.attr("color", "white");*/
// Add labels with background
const maxWidth = 100;
labels = svg.selectAll("g.label")
.data(data.features)
.enter()
.append("g")
.attr("class", "label")
.each(function(d) {
const g = d3.select(this);
const name = d.properties.name;
// Append the text
const text = g.append("text")
.attr("feature-name", d.properties.name)
.attr("font-size", "12px")
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("x", 0);
// Manually wrap text
const words = name.split(/\s+/);
let line = [];
let lineNumber = 0;
const lineHeight = 1.1; // ems
const x = 0;
const y = 0;
let tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", `${lineNumber * lineHeight}em`);
for (let i = 0; i < words.length; i++) {
line.push(words[i]);
tspan.text(line.join(" "));
// If text exceeds maxWidth, remove last word and start new line
if (tspan.node().getComputedTextLength() > maxWidth) {
line.pop();
tspan.text(line.join(" "));
line = [words[i]];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", `${++lineNumber * lineHeight}em`)
.text(words[i]);
}
}
// Measure the text
const bbox = text.node().getBBox();
// Move both text and rect left by half the text width to center
text.attr("x", -bbox.width / 2);
// Append rect behind text
g.insert("rect", "text")
.attr("x", bbox.x - 4)
.attr("y", bbox.y - 2)
.attr("width", bbox.width + 8)
.attr("height", bbox.height + 4)
.attr("fill", "white")
.attr("stroke", "black")
.attr("stroke-width", 0.5)
.attr("rx", 4)
.attr("ry", 4);
// Save bbox dimensions for use in `update()`
//g.attr("data-bbox-width", bbox.width);
g.attr("data-bbox-height", bbox.height);
});
// 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");
const lblVerticalOffset = 4;
//console.log("update");
circles.attr("cx", function(d) { return project(d.geometry.coordinates).x })
.attr("cy", function(d) { return project(d.geometry.coordinates).y });
/*labels.attr("x", function(d) { return project(d.geometry.coordinates).x - 8}) // offset to right of circle
.attr("y", function(d) { return project(d.geometry.coordinates).y - 20 }); // vertically center text*/
labels
.attr("transform", function(d) {
const p = project(d.geometry.coordinates);
const dy = -(+this.getAttribute("data-bbox-height") + lblVerticalOffset)
return `translate(${p.x}, ${p.y + dy})`;
});
//console.log(map.getZoom());
const labelNodes = labels.nodes();
for(let i = 0; i < labelNodes.length; i++){
for(let j = i + 1; j < labelNodes.length; j++){
if(isOverlapping(labelNodes[i], labelNodes[j])){
console.log("OVERLAAAPPPP!!!");
console.log(labelNodes[i]);
console.log(labelNodes[j]);
}
}
}
}
function isOverlapping(a,b){
const recta = a.getBoundingClientRect();
const rectb = b.getBoundingClientRect();
const aright_lt_bleft = recta.right < rectb.left;
const abottom_lt_btop = recta.bottom < rectb.top;
const aleft_gt_bright = recta.left > rectb.right;
const atop_gt_bbottom = recta.top > rectb.bottom;
const overlaping = !(aright_lt_bleft || aleft_gt_bright || abottom_lt_btop || atop_gt_bbottom);
if(overlaping){
const aName = a.querySelector("text").getAttribute("feature-name");
const bName = b.querySelector("text").getAttribute("feature-name");
console.log(`A: ${aName} (${(+recta.right).toFixed(4)}, ${recta.left}), B: ${bName}`);
console.log(aright_lt_bleft, abottom_lt_btop, aleft_gt_bright, atop_gt_bbottom);
}
return overlaping;
}
</script>

View File

@@ -4,8 +4,8 @@
<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.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js"></script>
<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">