Reputation: 349
I am drawing circles with every update using a smooth transition which goes from one location to another. Here is the code I am using...
function drawChart(newData)
{
var circles = slider.selectAll(".dot")
.data(newData);
circles.enter()
.append("circle")
.merge(circles)
.transition() // and apply changes to all of them
.duration(1000)
.ease(d3.easeLinear)
.attr("class", "dot")
.attr("r", 10.5)
.attr("cx", function(d,i) {
return Math.pow(d.open,i); })
.attr("cy", function(d,i) { return Math.pow(i,5)+d.close; })
.style("fill", function(d) { return color(d.class); });
circles.exit()
.remove();
}
This is how data is updated using the filterData function.
function filterData(dd){
var newData = dataset.filter(function(d) {
return d.date.getDate() == dd.getDate() && d.date.getMonth() == dd.getMonth();
})
drawChart(newData)
}
This code shows the simple circle and transition, whereas I want to have the transition in a way circles are leaving trails while moving as in this picture. .
Is there any way to do this? Any help would be appreciated.
Upvotes: 1
Views: 201
Reputation: 13129
I made your starting positions a little easier to mock, the true calculations are in the .tween
function. Note that I execute the function only a few times, otherwise you get a continuous flow of circles.
You can often find solutions like this by looking at similar problems. In this case, I based it on this answer, which led me to tween.
var svg = d3.select('svg');
var color = (v) => v;
var nTrails = 20;
function createTraceBall(x, y) {
svg.append('circle')
.classed('shadow', true)
.attr('cx', x)
.attr('cy', y)
.attr('r', 10)
.style('fill', 'grey')
.style('opacity', 0.5)
.transition()
.duration(500)
.ease(d3.easeLinear)
.style('fill', 'lightgrey')
.style('opacity', 0.1)
.attr('r', 3)
.remove();
}
function drawChart(newData) {
var circles = svg.selectAll(".dot")
.data(newData);
circles.enter()
.append("circle")
.attr("cx", (d) => d.open.x)
.attr("cy", (d) => d.open.y)
.merge(circles)
.transition() // and apply changes to all of them
.duration(1000)
.ease(d3.easeLinear)
.tween("shadow", function(d) {
var xRange = d.close.x - d.open.x;
var yRange = d.close.y - d.open.y;
var nextT = 0;
return function(t) {
// t is in [0, 1), and we only want to execute it nTrails times
if(t > nextT) {
nextT += 1 / nTrails;
createTraceBall(
d.open.x + xRange * t,
d.open.y + yRange * t
);
}
};
})
.attr("class", "dot")
.attr("r", 10.5)
.attr("cx", (d) => d.close.x)
.attr("cy", (d) => d.close.y)
.style("fill", function(d) { return color(d.class); });
circles.exit()
.remove();
}
drawChart([
{open: {x: 20, y: 20}, close: {x: 150, y: 150}, class: 'red'},
{open: {x: 150, y: 20}, close: {x: 20, y: 150}, class: 'blue'},
{open: {x: 20, y: 20}, close: {x: 150, y: 20}, class: 'green'}
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
Upvotes: 2