d3转换有哪些属性变化?

Jal*_*Jal 2 html javascript animation svg d3.js

我试图了解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);
Run Code Online (Sandbox Code Playgroud)
  1. 转换是在转换之前影响任何语句还是在转换之后仅转换效果语句

  2. 多个过渡如何运作?

Ger*_*ado 8

你的第二个问题......

  1. 多个过渡如何运作?

回答很简单.这里,API很清楚:

transition.transition()

返回与此转换相同的所选元素的新转换,计划在此转换结束时启动.

因此,新的转换将在前一个转换完成时开始,依此类推.让我们来看看它:

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")
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
Run Code Online (Sandbox Code Playgroud)

有趣的问题

然而,这里有趣的问题是你的第一个问题:

  1. 转换是在转换之前影响任何语句还是在转换之后仅转换效果语句?

嗯,这也是非常基本的:该transition()方法在起始值和目标值之间创建转换.您必须在转换(起始值)之前和转换之后(目标值)设置属性.

问题是先前未设置的属性将具有null值.

让我们看看它:没有指定height矩形,它是null:

var rect = d3.select("svg").append("rect");

console.log(rect.attr("height"))
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
Run Code Online (Sandbox Code Playgroud)

因此,如果在转换之前未设置高度,则没有关于高度的平滑过渡:

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

这里有一个有趣的观点:我写了一个答案(现已删除,> 10k的用户可以看到它),解释说插补器不能插入null给定值.但是,它可以插值:

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

所以,这里发生的事情有点复杂.使用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);
  });
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
Run Code Online (Sandbox Code Playgroud)

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

经过一番调查,在我看来这transition()是数字目标值转换为字符串(如100"100").这很奇怪,因为API明确说明......

...使用以下算法,根据目标值的类型选择插补器:

  1. 如果value是数字,请使用interpolateNumber.
  2. 如果value是颜色或可强制颜色的字符串,请使用interpolateRgb.
  3. 使用interpolateString.

这是源代码,请看最后一行:

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 ------------------------------------------^
}
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,它正在将值强制转换为字符串.因此,转换将不起作用,因为它将使用interpolateString而不是interpolateNumber:

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

结论

transition()创建从起始值到目标值的转换.如果未设置起始值,则默认为null.但是,作为transition()用途interpolateString,插值将无法正常工作.

2017年11月18日更新

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

interpolateString(或interpolateRgb)是正确的行为.interpolateNumber永远不应该用于属性.

解释是价值喜欢"100px""1.3em"不适用interpolateNumber.所以,再次,不要依赖null起始值:始终在之前和之后设置属性transition().

感谢@altocumulus对GitHub问题的评论.