d3-jsnext
Version:
d3, but futuristic
141 lines (117 loc) • 3.7 kB
HTML
require( 'babel/register' );
<meta charset="utf-8">
<style>
table {
width: 960px;
border-spacing: 0;
border-collapse: collapse;
}
th, td {
padding: 4px;
}
th {
text-align: left;
}
td {
border: solid 1px #ccc;
text-align: right;
}
td.fail {
background: lightcoral;
}
td.success {
background: lightgreen;
}
</style>
<table>
<thead>
<th>start</th>
<th>end</th>
<th colspan=5>actual intermediate values</th>
<th>exp.</th>
<th>act.</th>
</thead>
<tbody>
</tbody>
</table>
<script src="../../d3.js"></script>
<script>
var format = d3.format(",.2f");
var tests = [
{start: 170, end: 225, expected: [ 170.00, -176.25, -162.50, -148.75, -135.00]},
{start: 225, end: 170, expected: [-135.00, -148.75, -162.50, -176.25, 170.00]},
{start: -170, end: -225, expected: [-170.00, 176.25, 162.50, 148.75, 135.00]},
{start: -225, end: -170, expected: [ 135.00, 148.75, 162.50, 176.25, -170.00]},
{start: -170, end: 170, expected: [-170.00, -175.00, 180.00, 175.00, 170.00]},
{start: -170, end: 0, expected: [-170.00, -127.50, -85.00, -42.50, 0.00]},
{start: 170, end: 0, expected: [ 170.00, 127.50, 85.00, 42.50, 0.00]},
{start: -180, end: 90, expected: [ 180.00, 157.50, 135.00, 112.50, 90.00]},
{start: 180, end: 90, expected: [ 180.00, 157.50, 135.00, 112.50, 90.00]},
{start: -180, end: -90, expected: [-180.00, -157.50, -135.00, -112.50, -90.00]},
{start: 180, end: -90, expected: [ 180.00, -157.50, -135.00, -112.50, -90.00]},
{start: 780, end: -90, expected: [ 60.00, 22.50, -15.00, -52.50, -90.00]}
];
var tr = d3.select("tbody").selectAll("tr")
.data(tests)
.enter().append("tr");
tr.append("td")
.text(function(d) { return format(d.start); });
tr.append("td")
.text(function(d) { return format(d.end); });
tr.selectAll(".actual")
.data(function(d) {
var interpolate = d3.interpolateTransform("rotate(" + d.start + ")", "rotate(" + d.end + ")");
return d.expected.map(function(expected, i) {
return {
expected: expected,
actual: d3.transform(interpolate(i / 4)).rotate
};
});
})
.enter().append("td")
.text(function(d, i) { return format(d.actual); })
.attr("class", function(d) { return Math.abs(d.actual - d.expected) < .01 ? "success" : "fail"; });
var ga = tr.append("td").attr("width", 40).append("svg")
.attr("width", 40)
.attr("height", 20)
.append("g")
.attr("transform", "translate(20,10)")
.append("g")
.each(animateExpected);
ga.append("path")
.attr("d", d3.svg.symbol().type("cross").size(120));
ga.append("circle")
.attr("cx", 8)
.attr("r", 4);
var gb = tr.append("td").attr("width", 40).append("svg")
.attr("width", 40)
.attr("height", 20)
.append("g")
.attr("transform", "translate(20,10)")
.append("g")
.each(animateActual);
gb.append("path")
.attr("d", d3.svg.symbol().type("cross").size(120));
gb.append("circle")
.attr("cx", 8)
.attr("r", 4);
function animateExpected(d) {
d3.select(this).transition()
.duration(2500)
.attrTween("transform", function(d) {
var a = d.start % 360, b = d.end % 360;
if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
return d3.interpolateString("rotate(" + a + ")", "rotate(" + b + ")");
})
.each("end", animateExpected);
}
function animateActual(d) {
d3.select(this)
.attr("transform", "rotate(" + d.start + ")")
.transition()
.duration(2500)
.attr("transform", "rotate(" + d.end + ")")
.each("end", animateActual);
}
</script>