javascript - d3转换会改变哪些属性?

标签 javascript html animation d3.js svg

我试图了解什么在d3中完全过渡。

例如

var bars = svg.selectAll(null)
  .data(my_values)
  .enter()
  .append("rect") // statement before transition
  .attr("x", 10)  // statement before transition
  .transition()   // transition
  .delay(200)
  .duration(1500)
  .attr("height", 10) // statement after transition
  .transition()   // another transition
  .delay(200)
  .duration(1500);
  • 过渡会影响过渡之前的任何语句还是仅影响过渡后的语句
  • 多个过渡如何工作?
  • 最佳答案

    你的第二个问题...

    1. How does multiple transition work?


    答案很简单。在这里,API很清楚:

    transition.transition()

    Returns a new transition on the same selected elements as this transition, scheduled to start when this transition ends.



    因此,新过渡将在上一个过渡完成时开始,依此类推。让我们来看看它:

    var rect = d3.select("svg").append("rect")
      .attr("width", 100)
      .attr("height", 0)
      .style("fill", "black")
      .transition()
      .duration(1000)
      .attr("height", 100)
      .transition()
      .duration(1000)
      .style("fill", "teal")
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>


    有趣的问题

    但是,这里有趣的问题是您的第一个问题:

    1. Does the transition effect any statement before the transition or does the transition effect only statement after the transition?


    嗯,这也很基础:transition()方法在起始值和目标值之间创建过渡。您必须在过渡之前(起始值)和过渡之后(目标值)设置属性。

    问题在于先前未设置的属性将具有null值。

    让我们看一下:在不指定矩形的height的情况下,它是null:

    var rect = d3.select("svg").append("rect");
    
    console.log(rect.attr("height"))
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>


    因此,如果未在过渡前设置高度,则不会有平滑的过渡:

    var rect = d3.select("svg").append("rect")
      .attr("width", 100)
      .transition()
      .duration(1000)
      .attr("height", 100);
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>


    有趣的是:我写了一个答案(现已删除,> 10k的用户可以看到),解释说插值器无法从null插值到给定值。但是,可以进行插值:

    var interpolator = d3.interpolateNumber(null, 100);
    d3.range(0,1.1,.1).forEach(function(d){
    	console.log(interpolator(d))
    });
    <script src="https://d3js.org/d3.v4.min.js"></script>


    因此,这里发生的事情更加复杂。使用interpolateNumber,我们可以从null插值到给定值。看一下这个没有设置height的演示:

    var rect = d3.select("svg").append("rect")
      .attr("width", 100)
      .transition()
      .duration(1000)
      .attrTween("height", function() {
        return d3.interpolateNumber(d3.select(this).attr("height"), 100);
      });
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>


    当您在转换前未设置属性时,为什么默认的transition.attr()不起作用?

    经过一番调查,在我看来transition()正在将数字目标值转换为字符串(例如100"100")。这很奇怪,因为API explicitly says表示...

    ... an interpolator is chosen based on the type of the target value, using the following algorithm:

    1. If value is a number, use interpolateNumber.
    2. If value is a color or a string coercible to a color, use interpolateRgb.
    3. Use interpolateString.


    这是source code,请看最后一行:
    export default function(name, value) {
        var fullname = namespace(name),
            i = fullname === "transform" ? interpolateTransform : interpolate;
        return this.attrTween(name, typeof value === "function" 
            ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) 
            : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) 
            : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value + ""));
            //converting to string here ------------------------------------------^
    }
    

    如我们所见,它将值强制为字符串。因此,转换将不起作用,因为它将使用interpolateString而不是interpolateNumber:

    var interpolator = d3.interpolateString(null, "100");
    d3.range(0,1.1,.1).forEach(function(d){
    	console.log(interpolator(d))
    });
    <script src="https://d3js.org/d3.v4.min.js"></script>


    结论
    transition()创建从起始值到目标值的过渡。如果未设置起始值,则默认为null。但是,由于transition()使用interpolateString,因此插值将无法正常工作。

    2017年11月11日更新

    根据Mike Bostock(D3创建者)的说法,源代码是正确的(因此,文档是错误的)。正如他在GitHub issue中所说:

    interpolateString (or interpolateRgb) is the correct behavior here. interpolateNumber should never be used for attributes.



    原因是"100px""1.3em"之类的值不适用于interpolateNumber。因此,再次,不要依赖null的起始值:始终在transition()之前和之后设置属性。

    感谢@altocumulus对GitHub问题发表评论。

    关于javascript - d3转换会改变哪些属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47339762/

    相关文章:

    html - 自定义 CSS 输入字段问题

    android - 在启动 CustomViewPager 时启动动画

    iphone - UIImageView 动画在第一次运行时滞后

    javascript - 如何绑定(bind)CSS动画持续时间滚动

    javascript - 创建玩家对象的两个实例,而不是使用静态实例

    javascript - 将绑定(bind)参数传递给 CSS

    android - 如何在android中制作流畅的帧动画?

    javascript - 如何与 Cucumber 框架共享 Protractor 中的 webdriver

    javascript - 如何调整选项中特定文本的大小或应用样式

    javascript - 删除数组的重复数组: javascript