【问题标题】:Using the selection index in looped d3.js transition在循环的 d3.js 过渡中使用选择索引
【发布时间】:2021-05-16 11:24:37
【问题描述】:

在 d3.js 中使用转换我正在尝试使用其中元素的索引来更新选择的属性(即(d, i) => (t => f(i, t))。第一次运行动画效果很好,但是当第二次运行循环时,传递给我的转换函数的索引 i 对于每个元素默认为 0,因此每个元素开始以相同的方式运行.我已经包含了一个最小的演示(请注意,虽然对于这个实际问题有更好的方法来解决这个问题,但对于我正在处理的实际问题来说并非如此)。

取消注释 console.log(i) 我已将其注释掉的地方证实了问题。

我觉得这里缺少 d3.js 的内部工作原理。我的(模糊的)解释是,第二次调用 d3.active(this) 时事情会出轨,导致选择以某种方式分解为其组成部分。

            
let svg = d3.select("svg")
              .attr("width", 700)
            
let pts = [0, 10, 20, 30, 40, 50]

let rects = svg.append("g")
  .selectAll("rect")
  .data(pts)
  .enter()
    .append("rect")
    .attr("x", d => d*12)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .attr("opacity", (d, i) => i/10)

rects.transition()
  .duration(3000)
  .ease(d3.easeLinear)
  .on("start", function repeat() {
    d3.active(this)
      .attrTween("opacity", (d, i) => {
        return function(t) {
          //console.log(i)
          return i/10 + t
        }
    })
      .transition()
      .duration(3000)
      .ease(d3.easeLinear)
      .attrTween("opacity", (d, i) => {
        return function(t) {
          return 1 - t * (1 - i/10)
        }
    })
      .transition()
      .on("start", repeat)
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

【问题讨论】:

    标签: javascript html svg d3.js


    【解决方案1】:

    具有不同的初始不透明度,使用一个函数,根据初始不透明度在时间间隔内将非零不透明度转换为 0,然后以恒定超时将其转换回 1:

    const transitOpacity = el => {
          const opacity = parseFloat(el.attr('opacity'));
          let delay, target;
          if (opacity > 0) {
            delay = 3000 * opacity;
            target = 0;
          }
          else {
            delay = 3000;
            target = 1;
          }
          el.transition().duration(delay).attr('opacity', target);
          setTimeout(() => transitOpacity(el), delay);
        }
    

    查看它在 sn-p 中的工作:

    let svg = d3.select("svg").attr("width", 700)
                
    
    let pts = [0, 10, 20, 30, 40, 50]
    
    const transitOpacity = el => {
      const opacity = parseFloat(el.attr('opacity'));
      let delay, target;
      if (opacity > 0) {
        delay = 3000 * opacity;
        target = 0;
      }
      else {
        delay = 3000;
        target = 1;
      }
      el.transition().duration(delay).attr('opacity', target);
      setTimeout(() => transitOpacity(el), delay);
    }
    
    let rects = svg.append("g")
      .selectAll("rect")
      .data(pts)
      .enter()
        .append("rect")
        .attr("x", d => d*12)
        .attr("y", 0)
        .attr("width", 100)
        .attr("height", 100)
        .attr("opacity", (d, i) => i / pts.length)
        .each(function() {
          const el = d3.select(this);
          transitOpacity(el);
        })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg />

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多