简体   繁体   English

在 D3 转换中获取预期的属性值

[英]Getting expected attribute value in D3 transition

For example I have a transition:例如我有一个过渡:

var sel = container.selectAll('div')
    .transition()
    .duration(1000)
    .attr('transform', 'translate(100,500)');

At some moment I need to know where some of the elements lands to, eg在某些时候,我需要知道某些元素的位置,例如

setTimeout(() => {
    var value = d3.select('div#target')
        .expectedAttr('transform');
    assertEqual(value, 'translate(100,500)');
}, 500);

Is there built-in feature like this in D3? D3 中是否有这样的内置功能? Otherwise I will have to write my own wrapper over d3.transition().attr() method for storing values passed to it.否则我将不得不在d3.transition().attr()方法上编写自己的包装器来存储传递给它的值。

Edit编辑

I've found out that D3 creates __transition__ field on elements, which seems to contain info regarding the transition, but I see no way to find a target attribute value there.我发现 D3 在元素上创建了__transition__字段,它似乎包含有关转换的信息,但我看不到在那里找到目标属性值的方法。

At first I thought this would not be possible because the target value seemed to be inaccessibly hidden by a closure.起初我认为这是不可能的,因为目标值似乎被闭包无法访问。 With a little trick, though, this value can be retrieved.不过,通过一个小技巧,可以检索此值。

You have to keep in mind that, when calling transition.attr() , D3 will do the following:您必须记住,在调用transition.attr() ,D3 将执行以下操作:

For each selected element, creates an attribute tween for the attribute with the specified name to the specified target value.对于每个选定的元素,为具有指定名称到指定目标值的属性创建一个属性补间

This automatically created tween can be accessed by calling transition.attrTween(attrName) .这个自动创建的补间可以通过调用transition.attrTween(attrName)来访问。

When this tween gets called by D3 it will return an interpolator .当这个 tween 被 D3 调用时,它将返回一个interpolator This in turn has access to the target value which was closed over when creating the interpolator.这反过来又可以访问在创建插值器时关闭的目标值。 When reading further down the docs the real trick becomes obvious:当进一步阅读文档时,真正的技巧变得显而易见:

The returned interpolator is then invoked for each frame of the transition, in order, being passed the eased time t , typically in the range [0, 1].然后为转换的每一帧调用返回的内插器,依次传递缓和时间t ,通常在 [0, 1] 范围内。

Knowing that the final value for t – at the end of the transition – will be 1 , you can call the previously obtained interpolator with this value which will yield the target value of the transition.知道 t 的最终值 - 在转换结束时 - 将是1 ,您可以使用此值调用先前获得的插值器,这将产生转换的目标值。

var targetValue = transition 
  .attrTween("x2")            // Get the tween for the desired attribute
  .call(line.node())          // Call the tween to get the interpolator
  (1);                        // Call the interpolator with 1 to get the target value

The following example shows this by printing the target value for an already running transition.以下示例通过打印已运行转换的目标值来说明这一点。

 var line = d3.select("line"); line .transition() .duration(2000) .attr("x2", 100); setTimeout(function() { var transition = d3.active(line.node()) // Get the active transition on the line var targetValue = transition .attrTween("x2") // Get the tween for the desired attribute .call(line.node()) // Call the tween to get the interpolator (1); // Call the interpolator with 1 to get the target value console.log(targetValue); // 100 }, 1000);
 <script src="https://d3js.org/d3.v4.js"></script> <svg><line x2="0" y2="100" stroke="black"></line></svg>

The same holds true for style transitions where you would use transition.styleTween() to get the tween.这同样适用于样式转换,您将使用transition.styleTween()来获取补间。

Ran into this problem today and found altocumulus' answer very helpful.今天遇到了这个问题,发现高积云的回答很有帮助。 However, I discovered that (at least for the current d3-transition@2.0.0 ) if the current value is already at the target value, .call ing the attrTween will return null instead of the interpolator.然而,我发现(至少对于当前d3-transition@2.0.0 )如果当前值已经达到目标值, .call荷兰国际集团的attrTween将返回null ,而不是插值。

My solution wound up looking something like this:我的解决方案看起来像这样:

const attrTargetValue = (selection, attr) => {
  const interpolator = selection
    .attrTween(attr)
    .call(selection.node());
  return interpolator === null
    ? selection.selection().attr(attr)
    : interpolator(1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM