Working version
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user