在D3中获得转换值

时间:2015-11-09 17:34:45

标签: javascript d3.js

我每100毫秒获得一次位置并将它们应用到DOM中:

const div = d3.select(container).selectAll('div').data(positions)

div.enter()
  .append('div')

div.transition()
  .duration(100)
  .style({
    top: d => d.y,
    left: d => d.x,
  })

div.exit()
  .remove()

因此,元素可以在100毫秒内获得平滑动画,以获得下一个位置所需的100毫秒。这很好。

但我在DOM中有不同的元素依赖于第一个元素的位置。它们使用相同的位置数据进行渲染,但是在软件的不同模块中进行渲染。

我的问题是,此转换会插入其他模块无法使用的数据。这些其他模块的元素似乎提供了光学错误"可视化,因为它们基于原始数据。

示例:一个点移动到一个正方形并且正方形被突出显示,但点的位置被插值,并且正方形用于检查是否应该突出显示的位置不是。因此,即使该点不在其中,方形也会突出显示。

我如何解决这个问题?我可以在某处获取那些插值吗?

2 个答案:

答案 0 :(得分:3)

我能想到的最简单的方法是使用转换的attrTween,styleTween或tween方法(https://github.com/mbostock/d3/wiki/Transitions#attrTween)。它们采用必须返回函数的函数(插值器)。该插补器将被多次调用以执行转换,因此您可以继续调用回调(cb),以便通知其他模块有关更改。

selection.styleTween('top', function(){
  var interpol = d3.interpolate(0,10); //interpolate from 0 to 10
  return function(t) { // this guy will be called many times to calc transition
    // t will be changing from 0 to 1
    var val = interpol(t);
    cb(val); // <-- callback that will notify other modules about the change in value
    return val; // <-- you have to return val so d3 transitions element
  }
});

答案 1 :(得分:3)

如果我正确理解您,您希望完全控制补间功能:

  div
    .transition()
    .duration(1000)
    .tween("postion", function(d) {
      var div = d3.select(this),
        startTop = parseInt(div.style('top')),
        startLeft = parseInt(div.style('left')),  
        yInterp = d3.interpolateRound(startTop, d.y),
        xInterp = d3.interpolateRound(startLeft, d.x);
      return function(t) {            
        div.style("top", yInterp(t) + "px");
        div.style("left", xInterp(t) + "px");
      };
    });

工作代码:

&#13;
&#13;
<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  </head>

  <body>
    <div id="parent">
      <div style="width: 20px; top: 20px; left: 30px; height: 20px; background-color: steelblue; position: absolute"></div>
      <div style="width: 20px; top: 0px; left: 40px; height: 20px; background-color: orange; position: absolute"></div>
    </div>
    <script>
    
      var positions = [
        {x: 50, y: 50},
        {x: 100, y: 100}
      ];
    
      var div = d3.select('#parent')
        .selectAll('div')
        .data(positions);

      div
        .transition()
        .duration(1000)
        .tween("postion", function(d) {
          var div = d3.select(this),
            startTop = parseInt(div.style('top')),
            startLeft = parseInt(div.style('left')),  
            yInterp = d3.interpolateRound(startTop, d.y),
            xInterp = d3.interpolateRound(startLeft, d.x);
          return function(t) {            
            div.style("top", yInterp(t) + "px");
            div.style("left", xInterp(t) + "px");
          };
        });
    </script>
  </body>

</html>
&#13;
&#13;
&#13;