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)
转换是在转换之前影响任何语句还是在转换之后仅转换效果语句
多个过渡如何运作?
你的第二个问题......
- 多个过渡如何运作?
回答很简单.这里,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)
然而,这里有趣的问题是你的第一个问题:
- 转换是在转换之前影响任何语句还是在转换之后仅转换效果语句?
嗯,这也是非常基本的:该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明确说明......
...使用以下算法,根据目标值的类型选择插补器:
- 如果value是数字,请使用
interpolateNumber.- 如果value是颜色或可强制颜色的字符串,请使用
interpolateRgb.- 使用
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,插值将无法正常工作.
根据Mike Bostock(D3创建者)的说法,源代码是正确的(因此,文档是错误的).正如他在这个GitHub问题中所说:
interpolateString(或interpolateRgb)是正确的行为.interpolateNumber永远不应该用于属性.
解释是价值喜欢"100px"或"1.3em"不适用interpolateNumber.所以,再次,不要依赖null起始值:始终在之前和之后设置属性transition().
感谢@altocumulus对GitHub问题的评论.