如何使用d3.js制作顺序数据的动画? [英] How to do animation of sequential data with d3.js?

查看:141
本文介绍了如何使用d3.js制作顺序数据的动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个顺序数据。数据是分为30个步骤的数组。
第一步,我绘制初始数据。然后,我从第二步中获取数据,并将其与上一步中的数据进行比较。并进行一些动画/过渡。



现在,我想在其余28个步骤中重复动画。
如果我将使用这样的代码

  var old_data = start_data; 
for(var i = 0,i var new_data = rest_data [i];
var diff_data = diff(old_data,new_data);

var t0 = d3.transition()。duration(3000);
var selection = d3.selectAll(’g’)。data(diff_data)
selection.transition(t0).attr(‘my’,function(d,i){...});
old_data = new_data;
}

它是行不通的,因为transition()是异步代码。循环运行得更快而不是完成第一个动画。充其量我将在data [0]和data [29]之间创建一个动画。



用像我这样的顺序数据创建动画的最佳方法是什么? / p>

使用 d3.transition()。on('end',function(){...}),其中 function(){...} 一些带有闭包的函数,我将在其中存储 old_data rest_data 和其他变量?
我不喜欢这种解决方案,因为我有很多变量来计算 diff_data ,因此必须将其保留在结束符中。

解决方案

您是正确的: for 循环将运行到最后几乎是瞬间,它会同时调用这一系列转换,当然,
不会起作用。



有一些不同的解决方案这里。好消息是 transition()。on( end ... 只是其中之一,如果不需要,则不需要使用它。



我最喜欢的一个方法是使用 setTimeout 甚至更好地使用<$ c创建重复调用的函数$ c> d3.timeout 。



这是它的逻辑:

  var计数器= 0; //这当然是一个计数器

函数loop(){

//如果存在是下一个计数器索引的数据元素,请再次调用循环:
if(data [counter + 1]){d3.timeout(loop,delay)}

//访问使用此处的计数器
//并操纵选择

//增加计数器
counter ++;

}

看看这个演示:



  var data = [30,400,170,280,460,40,250]; var svg = d3.select( body).append( svg).attr ( width,500).attr( height,100); var circle = svg.append( circle).attr( cy,50).attr( cx,250).attr( r,10).attr( fill, tan).attr( stroke, black); var counter = 0; loop(); function loop(){if(data [counter + 1] ){d3.timeout(loop,1000)} circle.transition().duration(500).attr( cx,data [counter]); counter ++}  

 < script src = https:// d3js.org/d3.v4.min.js\"></script>


I have a sequential data. Data is an array divided into 30 steps. In the first step I draw initial data. Then I take data from second step, compare it with data from previous step. And make some animation/transition.

Now I want to repeat animation for the rest of 28 steps. If I will use code like this

var old_data = start_data;
for (var i = 0, i < rest_data.length; i++){
    var new_data = rest_data[i];
    var diff_data = diff(old_data, new_data);

    var t0 = d3.transition().duration(3000);
    var selection = d3.selectAll('g').data(diff_data)
    selection.transition(t0).attr('my', function(d,i) { ... });
    old_data = new_data;
}       

it will not work because transition() is async code.The loop run faster than complete the first animation. And at best I will have an animation between data[0] and data[29].

What is the best way to create an animation with sequential data like my?

Use d3.transition().on('end', function() {...}), where function() { ... } some function with closure where I will store old_data, rest_data and other variables? I don't like this solution because I have many variables to calculate diff_data, and I have to keep them in the closure.

解决方案

You are correct: the for loop will run to the end almost instantly, and it will simply call that bunch of transitions at the same time, which, of course, will not work.

There are some different solutions here. Good news is that transition().on("end"... is just one of them, you don't need to use it if you don't want.

My favourite one is creating a function that you call repeatedly with setTimeout or, even better, with d3.timeout.

This is the logic of it:

var counter = 0;//this is, of course, a counter

function loop(){

    //if there is a data element for the next counter index, call 'loop' again:
    if(data[counter + 1]){ d3.timeout(loop, delay)}

    //access the data using the counter here,
    //and manipulate the selection

    //increase the counter
    counter++;

}

Have a look at this demo:

var data = [30, 400, 170, 280, 460, 40, 250];
var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 100);
var circle = svg.append("circle")
  .attr("cy", 50)
  .attr("cx", 250)
  .attr("r", 10)
  .attr("fill", "tan")
  .attr("stroke", "black");

var counter = 0;

loop();

function loop() {
  if (data[counter + 1]) {
    d3.timeout(loop, 1000)
  }
  circle.transition()
    .duration(500)
    .attr("cx", data[counter]);
  counter++
}

<script src="https://d3js.org/d3.v4.min.js"></script>

这篇关于如何使用d3.js制作顺序数据的动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆