Skip to content

Instantly share code, notes, and snippets.

@tlfrd
Last active September 1, 2017 16:14
Show Gist options
  • Save tlfrd/3dedf0369f7d67843be17961550218d9 to your computer and use it in GitHub Desktop.
Save tlfrd/3dedf0369f7d67843be17961550218d9 to your computer and use it in GitHub Desktop.
Elbows (and Brackets)
license: mit

Playing with paths to create bracket and elbow connectors (1 + 2) for annotations.

TODO: Rewrite to use SVG path strings and add labels with line lengths.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.connector-b {
stroke: red;
stroke-width: 1px;
stroke-dasharray: 5,5;
}
.connector-a {
stroke: blue;
stroke-width: 1px;
stroke-dasharray: 5,5;
}
.connector-45 {
stroke: black;
stroke-width: 2px;
}
.connector-90 {
stroke: black;
stroke-width: 2px;
}
.connector-line {
opacity: 1;
stroke: #bbb;
stroke-width: 1px;
stroke-dasharray: 5,5;
}
circle {
fill: white;
}
</style>
</head>
<body>
<script>
var width = 960,
height = 500;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
var config = {
radius: 10
};
var data = [{x: 300, y: 200, colour: "cyan"}, {x: 500, y: 300, colour: "magenta"}];
var dragbehaviour = d3.drag()
.on("drag", dragged);
var points = svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", config.radius)
.style("fill", d => d.colour)
.call(dragbehaviour);
var connector = svg.append("line")
.attr("class", "connector-line")
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[1].x)
.attr("y2", data[1].y);
var connectorB = svg.append("line")
.attr("class", "connector-b")
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[0].x)
.attr("y2", data[0].y + calculateLine1().b);
var connectorA = svg.append("line")
.attr("class", "connector-a")
.attr("x1", data[0].x)
.attr("y1", data[0].y + calculateLine1().b)
.attr("x2", data[0].x + calculateLine1().c)
.attr("y2", data[0].y + calculateLine1().b);
var connector45 = svg.append("line")
.attr("class", "connector-45")
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[0].x + calculateLine1().a)
.attr("y2", data[0].y + calculateLine1().b);
var connector90 = svg.append("line")
.attr("class", "connector-90")
.attr("x1", data[0].x + calculateLine1().a)
.attr("y1", data[0].y + calculateLine1().b)
.attr("x2", data[1].x)
.attr("y2", data[1].y);
points.raise();
function dragged(d) {
d3.select(this)
.attr("cx", d.x = Math.max(0, Math.min(width, d3.event.x)))
.attr("cy", d.y = Math.max(0, Math.min(height, d3.event.y)));
connector
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[1].x)
.attr("y2", data[1].y);
connectorB
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[0].x)
.attr("y2", data[0].y + calculateLine1().b);
connectorA
.attr("x1", data[0].x)
.attr("y1", data[0].y + calculateLine1().b)
.attr("x2", data[0].x + calculateLine1().c)
.attr("y2", data[0].y + calculateLine1().b);
connector45
.attr("x1", data[0].x)
.attr("y1", data[0].y)
.attr("x2", data[0].x + calculateLine1().a)
.attr("y2", data[0].y + calculateLine1().b);
connector90
.attr("x1", data[0].x + calculateLine1().a)
.attr("y1", data[0].y + calculateLine1().b)
.attr("x2", data[1].x)
.attr("y2", data[1].y);
}
// Rewrite to use
function calculateLine1() {
var b = data[1].y - data[0].y;
var a = Math.abs(Math.tan(Math.PI / 4) * b);
var c = data[1].x - data[0].x;
var h = Math.sqrt(Math.pow(b, 2) + Math.pow(c, 2));
var ab = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
/*
Check if the line between the two points is less than
the hypotenuse between a and b
*/
if (h < ab) {
a = data[1].x - data[0].x;
b = Math.abs(Math.tan(Math.PI / 4) * a);
if ((data[1].y - data[0].y) < 0) {
b = -b;;
}
} else {
if ((data[1].x - data[0].x) < 0) {
a = -a;
}
}
return {a: a, b: b, c: c};
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment