d3转换有哪些属性变化? [英] What attributes does d3 transition change?

查看:68
本文介绍了d3转换有哪些属性变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



例如

  var bars = svg.selectAll(null)
.data(my_values)
.enter()
.append(rect)//转换前的语句
.attr(x,10)//转换前的语句
.transition()//转换
.delay(200)
.duration(1500)
。 attr(height,10)//转换后的语句
.transition()//另一个转换
.delay(200)
.duration(1500);




  1. 转换是否会在转换之前生效任何语句?转换后的转换效果唯一声明


  2. 多重转换是如何工作的?



解决方案

第二个问题...



  1. 多重过渡是如何工作的?


回答。这里的API很明确:

lockquote
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)

 < script src =https://d3js.org/d3.v4.min.js>< / script>< svg> < / svg>  



有趣的问题



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



  1. 转换是否会影响转换前的任何语句,或转换后是否仅转换影响语句?


好吧,这也是非常基本的: transition()方法会在起始值和目标值之间创建一个转换。你必须在转换之前(起始值)和转换之后(目标值)设置属性。



问题是以前没有设置的属性会有 null 值。让我们看看它:没有指定矩形的 height ,它是 null

/ code>:

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))}); pre>

< script src =https://d3js.org/d3.v4.min.js >< / script>

这里有点复杂。使用 interpolateNumber ,我们可以从 null 内插到一个给定的值。看看这个演示, height 没有设置:

 

 < script src =https://d3js.org/d3.v4.min.js>< / script>< ; svg>< / svg>  

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



经过一番调查,在我看来, transition()正在将数字目标值转换为一个字符串(例如 100 100)。这很奇怪,因为 API明确指出 ......


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


  1. 如果value是数字,则使用 interpolateNumber

  2. 如果value是颜色或一个字符串,可以使用 interpolateRgb

  3. 使用 interpolateString


以下是源代码,看看最后一行:

 导出默认函数(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 +));
//在这里转换为字符串---------------------------------------- - ^
}

正如我们所看到的,它将值强制转换为字符串。因此,转换不起作用,因为它将使用 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>   

$ b


$ b

transition( )创建从起始值到目标值的转换。如果起始值没有设置,它将默认为 null 。但是,当 transition()使用 interpolateString 时,插值将无法正常工作。
根据Mike Bostock(D3创建者)的说法,源代码是正确的(因此,文档是错的)。正如他在 GitHub问题中所说:


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

解释是, 100px1.3em不适用于 interpolateNumber 。因此,不要依赖 null 起始值:总是在转换之前和之后设置属性()

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


I am trying to understand what exactly gets transition in d3.

For example

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. Does the transition effect any statement before the transition or does the transition effect only statement after the transition

  2. How does multiple transition work?

解决方案

Your second question...

  1. How does multiple transition work?

Is quite simple to answer. Here, the API is clear:

transition.transition()

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

So, the new transition will start when the previous one finishes, and so on. Let's see it:

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>

The interesting question

However, the interesting question here is your first one:

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

Well, this is also quite basic: the transition() method creates a transition between a starting value and a target value. You have to set the attribute before the transition (the starting value) and after the transition (the target value).

The problem is that attributes not previously set will have a null value.

Let's see it: without specifying the height of the rectangle, it is 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>

Therefore, there is no smooth transition regarding the height if you don't set it before the transition:

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>

And here comes the interesting point: I wrote an answer (now deleted, users with >10k can see it) explaining that the interpolator cannot interpolate from null to a given value. However, it can interpolate:

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>

So, what is happening here is a bit more complicated. Using interpolateNumber we can interpolate from null to a given value. Look at this demo, where the height was not set:

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>

Why the default transition.attr() doesn't work when you don't set the attribute before the transition?

After some investigation, it seems to me that transition() is converting the numeric target value to a string (like 100 to "100"). This is very strange, because the API explicitly says that...

... 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.

Here is the source code, look at the last line:

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 ------------------------------------------^
}

As we can see, it's coercing the value to a string. Therefore, the transition will not work because it will use interpolateString instead of 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>

Conclusion

transition() creates a transition from a starting value to a target value. If the starting value is not set, it will default to null. However, as transition() uses interpolateString, the interpolation will not work properly.

Update in 18/11/2017

According to Mike Bostock (D3 creator), the source code is correct (and, therefore, the documentation is wrong). As he says in this GitHub issue:

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

The explanation is that values like "100px" or "1.3em" would not work with interpolateNumber. So, again, don't rely on null starting values: always set the attribute before and after the transition().

Thanks to @altocumulus for commenting on the GitHub issue.

这篇关于d3转换有哪些属性变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆