Skip to content

Instantly share code, notes, and snippets.

@proclamo-zz
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save proclamo-zz/75aa04c17393b89f81d9 to your computer and use it in GitHub Desktop.
Save proclamo-zz/75aa04c17393b89f81d9 to your computer and use it in GitHub Desktop.
Automatic labeling experiment step 1

This is the first step in an experiment on the problem of automatic positioning of labels on a map. You can drag de central label "Hello" and move over the other labels and you will see how the overlapped labels automatically change their positions. The function is called multiple times on each drag event, but the idea is to call only once on to a map.

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.handler {
cursor: move;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
fill: red;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript">
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var drag = d3.behavior.drag()
.on("drag", function(d) {
d3.select(this).attr("dx", d3.event.x).attr("dy", d3.event.y);
alignLabels();
});
var label = svg.append("text")
.attr("dx", width/2)
.attr("dy", height/2)
.attr("class", "label handler")
.text("Hello")
.call(drag);
var data = [];
for (var i = 0; i < 200; i++) {
data.push(Math.round(Math.random() * 300));
}
svg.selectAll('.label')
.data(data)
.enter()
.append("text")
.attr("dx", function(d) { return width - d * Math.random() * 10; })
.attr("dy", function(d) { return height - d * Math.random() * 10; })
.attr("class", "label")
.text(function(d) { return d; });
var next = function(label) {
var box = getBox(label);
var pos = label.attr("data-pos") || 0;
pos++;
if (pos === 8) {
pos = 0;
}
label.attr("data-pos", pos);
switch (pos) {
case 0:
label.attr("transform", "translate(0,0)");
break;
case 1:
label.attr("transform", "translate(0, " + box.height + ")");
break;
case 2:
label.attr("transform", "translate(" + (-box.width/2) + ", " + box.height + ")");
break;
case 3:
label.attr("transform", "translate(" + (-box.width) + ", " + box.height + ")");
break;
case 4:
label.attr("transform", "translate(" + (-box.width) + ", 0)");
break;
case 5:
label.attr("transform", "translate(" + (-box.width) + ", " + (-box.height) + ")");
break;
case 6:
label.attr("transform", "translate(" + (-box.width/2) + ", " + (-box.height) + ")");
break;
case 7:
label.attr("transform", "translate(0, " + (-box.height) + ")");
break;
}
}
var overlaps = function(a, b) {
return (
(a.left <= b.left && b.left <= a.right)
||
(a.left <= b.right && b.right <= a.right)
)
&&
(
(a.top <= b.top && b.top <= a.bottom)
||
(a.top <= b.bottom && b.bottom <= a.bottom)
);
}
var getBox = function(d) {
return d[0][0].getBoundingClientRect();
}
var alignLabels = function() {
var texts = d3.selectAll(".label");
texts.each(function() {
var current = this;
var box_text = getBox(d3.select(current));
var overlappeds = texts[0].filter(function(d) {
if (d === current) return false;
return overlaps(box_text, getBox(d3.select(d)));
});
overlappeds.forEach(function(el) {
next(d3.select(el));
});
});
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment