代码之家  ›  专栏  ›  技术社区  ›  Ahmad

为什么是。delay()未正确迭代?

  •  2
  • Ahmad  · 技术社区  · 7 年前

    我正在使用 d3.v4.min.js 在下面的代码段中生成条形图。 不知什么原因 transition().delay() 函数的行为异常。 我将函数作为参数传递 (d,i)=>{return i*100} 使每列在开始动画之前等待100毫秒的倍数。至少,这是我所期望的,因为 i 的值应为 0,1,2,...etc

    但是,所有列都会立即启动动画,我已将根本原因追溯到 在里面 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 回复  |  直到 7 年前
        1
  •  2
  •   Gerardo Furtado    4 年前

    在您的代码中 enter 是选择的 <g> 元素,每个元素只有一个 <rect> .因此,使用 select 而不是 selectAll :

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

    这是您修改后的代码:

    //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);});
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>

    只是为了让你了解 选择 全选 (下表中有更多信息),您可以使用 全选 ,但与 进来 选择例如:

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

    这是:

    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);});
    <脚本src=”https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js“></script>

    表格: 之间的差异 选择 全选

    方法 选择() selectAll()
    选择 选择与选择器字符串匹配的第一个元素 选择与选择器字符串匹配的所有元素
    分组 不影响分组 影响分组
    数据传播 传播数据 不传播数据