为什么.delay()没有正确迭代?

时间:2018-04-24 12:51:01

标签: javascript d3.js

我正在使用d3.v4.min.js在下面的代码段中生成条形图。 由于某些未知原因,transition().delay()函数表现得很奇怪。 我将函数(d,i)=>{return i*100}作为参数传递,以使每列在开始动画之前等待100毫秒的倍数。至少,这是我预期会发生的事情,因为i的值应为0,1,2,...etc

但是,所有列都会立即启动动画,并且我已将根本原因追溯到i函数中的dealy()。它在所有迭代中都固定为零。

我做错了什么?

//jshint esnext:true

const margin = {top: 30, bottom: 70, left: 40, right: 10};
const width = 600, height=200;
const color = d3.scaleOrdinal(d3.schemeCategory20);
const data = [{name:'ahmad',age:22},
              {name:'saleh',age:15},
              {name:'fulan',age:35},
              {name:'fazil',age:48},
              {name:'majid',age:50}
             ];
const svg = d3.select("body").append("svg")
              .attr("width",width)
              .attr("height",height)
              .style("background-color","beige");

const max = d3.max(data,d=>{return d.age;});
const min = 0; //1 || d3.min(data,d=>{return d.age;});
const y = d3.scaleLinear().domain([min,max]).range([height-margin.bottom,margin.top]);
const yAxis = d3.axisLeft().scale(y);

const x = d3.scaleBand()
            .domain(data.map(d=>{return d.name;}))
            .range([margin.left,width-margin.right])
            .padding(0.4);

const xAxis = d3.axisBottom().scale(x);

svg.append("g").attr("class","y axis").attr("transform","translate("+margin.left+",0)").call(yAxis);
svg.append("g").attr("class","x axis").attr("transform","translate(0,"+(height-margin.bottom)+")").call(xAxis);

const selection = svg.selectAll(".name").data(data);
const enter = selection.enter().append("g").attr("class","name");
const exit = selection.exit();

enter.append("rect").attr("x",d=>{return x(d.name);}).attr("y",y(0)).attr("width",x.bandwidth()).attr("height",0).attr("fill",d=>{return color(d.name);});



// here is the problem. I can't figure out why animation is not delayed per iteration.
enter.selectAll("rect")
      .transition()
      .delay((d,i)=>{
         /*console.log(i);*/  // this prints 0 for all iterations. Why?  
         return 100*i;
       })
      .duration(1000)
      .ease(d3.easeElastic)
     .attr("y",d=>{return y(d.age);})
     .attr("height",d=>{return y(0)-y(d.age);});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>

1 个答案:

答案 0 :(得分:2)

在您的代码中,enter是一系列<g>个元素,每个元素只有一个<rect>。因此,请使用select代替selectAll

enter.select("rect")
    //etc...

以下是您修改后的代码:

&#13;
&#13;
//jshint esnext:true

const margin = {top: 30, bottom: 70, left: 40, right: 10};
const width = 600, height=200;
const color = d3.scaleOrdinal(d3.schemeCategory20);
const data = [{name:'ahmad',age:22},
              {name:'saleh',age:15},
              {name:'fulan',age:35},
              {name:'fazil',age:48},
              {name:'majid',age:50}
             ];
const svg = d3.select("body").append("svg")
              .attr("width",width)
              .attr("height",height)
              .style("background-color","beige");

const max = d3.max(data,d=>{return d.age;});
const min = 0; //1 || d3.min(data,d=>{return d.age;});
const y = d3.scaleLinear().domain([min,max]).range([height-margin.bottom,margin.top]);
const yAxis = d3.axisLeft().scale(y);

const x = d3.scaleBand()
            .domain(data.map(d=>{return d.name;}))
            .range([margin.left,width-margin.right])
            .padding(0.4);

const xAxis = d3.axisBottom().scale(x);

svg.append("g").attr("class","y axis").attr("transform","translate("+margin.left+",0)").call(yAxis);
svg.append("g").attr("class","x axis").attr("transform","translate(0,"+(height-margin.bottom)+")").call(xAxis);

const selection = svg.selectAll(".name").data(data);
const enter = selection.enter().append("g").attr("class","name");
const exit = selection.exit();

enter.append("rect").attr("x",d=>{return x(d.name);}).attr("y",y(0)).attr("width",x.bandwidth()).attr("height",0).attr("fill",d=>{return color(d.name);});



// here is the problem. I can't figure out why animation is not delayed per iteration.
enter.select("rect")
      .transition()
      .delay((d,i)=>{
         /*console.log(i);*/  // this prints 0 for all iterations. Why?  
         return 100*i;
       })
      .duration(1000)
      .ease(d3.easeElastic)
     .attr("y",d=>{return y(d.age);})
     .attr("height",d=>{return y(0)-y(d.age);});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
&#13;
&#13;
&#13;

只是为了让您了解selectselectAll之间的差异(下表中有更多内容),您可以使用selectAll,但不能使用enter选项。例如:

svg.selectAll("rect")
    //etc...

这是:

&#13;
&#13;
const margin = {top: 30, bottom: 70, left: 40, right: 10};
const width = 600, height=200;
const color = d3.scaleOrdinal(d3.schemeCategory20);
const data = [{name:'ahmad',age:22},
              {name:'saleh',age:15},
              {name:'fulan',age:35},
              {name:'fazil',age:48},
              {name:'majid',age:50}
             ];
const svg = d3.select("body").append("svg")
              .attr("width",width)
              .attr("height",height)
              .style("background-color","beige");

const max = d3.max(data,d=>{return d.age;});
const min = 0; //1 || d3.min(data,d=>{return d.age;});
const y = d3.scaleLinear().domain([min,max]).range([height-margin.bottom,margin.top]);
const yAxis = d3.axisLeft().scale(y);

const x = d3.scaleBand()
            .domain(data.map(d=>{return d.name;}))
            .range([margin.left,width-margin.right])
            .padding(0.4);

const xAxis = d3.axisBottom().scale(x);

svg.append("g").attr("class","y axis").attr("transform","translate("+margin.left+",0)").call(yAxis);
svg.append("g").attr("class","x axis").attr("transform","translate(0,"+(height-margin.bottom)+")").call(xAxis);

const selection = svg.selectAll(".name").data(data);
const enter = selection.enter().append("g").attr("class","name");
const exit = selection.exit();

enter.append("rect").attr("x",d=>{return x(d.name);}).attr("y",y(0)).attr("width",x.bandwidth()).attr("height",0).attr("fill",d=>{return color(d.name);});


// here is the problem. I can't figure out why animation is not delayed per iteration.
svg.selectAll("rect")
      .transition()
      .delay((d,i)=>{
         /*console.log(i);*/  // this prints 0 for all iterations. Why?  
         return 100*i;
       })
      .duration(1000)
      .ease(d3.easeElastic)
     .attr("y",d=>{return y(d.age);})
     .attr("height",d=>{return y(0)-y(d.age);});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
&#13;
&#13;
&#13;

表格selectselectAll之间的差异。

+--------------------+----------------------------------+----------------------------+
| Method             |              select()            |         selectAll()        |
+--------------------+----------------------------------+----------------------------+
| Selection          | selects the first element        | selects all elements that  |
|                    | that matches the selector string | match the selector string  |
+--------------------+----------------------------------+----------------------------+
| Grouping           | Does not affect grouping         | Affects grouping           |
+--------------------+----------------------------------+----------------------------+
| Data propagation   | Propagates data                  | Doesn't propagate data     |
+--------------------+----------------------------------+----------------------------+