Skip to content

Instantly share code, notes, and snippets.

@bycoffe
Last active March 29, 2017 13:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bycoffe/c3849a0b15234d7e32fc to your computer and use it in GitHub Desktop.
Save bycoffe/c3849a0b15234d7e32fc to your computer and use it in GitHub Desktop.
Element rotation with point-along-path interpolation
<!DOCTYPE html>
<meta charset="utf-8">
<style>
#chart path.line {
fill: none;
stroke-width: 1;
stroke: #666;
stroke-dasharray: 3,3;
}
line {
stroke: #000;
stroke-width: 1;
}
text {
font-family: Helvetica, sans-serif;
font-size: 11px;
text-anchor: middle;
}
</style>
<body>
<div id="chart"></div>
</body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 800 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
x = d3.scale.linear()
.domain([0, 20])
.range([10, width]),
y = d3.scale.linear()
.domain([0, 1])
.range([height, 0]),
data = d3.range(x.domain()[1]).map(function(x) {
return Math.random();
}),
line = d3.svg.line()
.interpolate("basis")
.x(function(d, i) {
return x(i);
})
.y(y),
svg = d3.select("#chart").append("svg").attr({
width: width + margin.left + margin.right,
height: height + margin.top + margin.bottom
}),
g = svg.append("g").attr({
transform: "translate(" + margin.left + "," + margin.top + ")"
}),
path = g.append("path")
.datum(data)
.attr({
"class": "line",
d: line
})
pointer = g.append("g"),
label = pointer.append("text")
.attr({
transform: "translate(0, -10)"
})
.text("Hi!"),
tri = pointer.append("path")
.attr({
"class": "tri",
d: d3.svg.symbol().type("triangle-down").size(50)()
});
var direction = -1,
atLength;
// From http://bl.ocks.org/mbostock/1705868
function transition() {
direction *= -1;
pointer.transition()
.ease("linear")
.duration(10000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
}
transition();
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
atLength = direction === 1 ? (t * l) : (l - (t * l));
var p1 = path.getPointAtLength(atLength),
p2 = path.getPointAtLength((atLength)+direction),
angle = Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
label.text(Math.round(angle) + "°");
return "translate(" + p1.x + "," + p1.y + ")rotate(" + angle + ")";
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment