A somewhat crazy method for turning an asynchronous d3 transition into something that can be paused/fast-forwarded/rewound while still using the nice syntax, easing, interpolation, etc. of d3.transition
.
After a transition is declared with normal syntax, calling .record()
on a selection inspects each element in a selection for the internals of its most recent transition. It generates an array of tweeners based on the transitions' tweens, the easing, and the elements' data. It then returns a wrapper function that will loop through and apply all of those tweeners for any arbitrary time value t (between 0 and 1).
This operates on the entire set of elements in the transition, but you could make it per-element with some changes.
This version only records the most recent transition and ignores delays. For a version that respects delays and chained transitions, see this example.
forked from veltman's block: Transition hacking
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
text-align: center;
font: 16px sans-serif;
}
button {
margin: 0 0.5em;
}
circle {
stroke: none;
fill: #de1e3d;
opacity: 0.8;
}
</style>
<body>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.14/d3.min.js"></script>
<script src="d3-record.js"></script>
<script>
var width = 760,
height = 200,
margin = 100;
var svg = d3.select("body").append("svg")
.attr("width",width + margin * 2)
.attr("height",height + margin * 2)
.append("g")
.attr("transform","translate(" + margin + " " + margin + ")")
var dots = svg.selectAll("circle")
.data(d3.range(2))
.enter()
.append("circle")
.attr("r",50)
.attr("cx",function(d){
return d ? width : 0;
})
.attr("cy",height / 2);
// Declare a normal transition
dots.transition()
.duration(3000)
.style("fill",function(d){
return d ? "#0e88ba" : "#fc0";
})
.attr("cx",function(d){
return d ? 0 : width;
})
.attr("r",function(d){
return d ? 100 : 25;
});
// "Record" the transition into a function that can jump to any time
var jumpToTime = dots.record();
d3.select("body").append("div")
.text("Jump to: ")
.selectAll("button")
.data(d3.range(0,1.1,0.1))
.enter()
.append("button")
.text(function(d){
return (d * 100) + "%";
})
.on("click",jumpToTime);
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.14/d3.min.js