本文介绍了使用数字时,d3 v5.8是否释放了样式的过渡?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中有d3 v5代码,该代码使用数字转换div的高度.自从今天的v5.8版本发布以来,这不再起作用:

d3.select("div").transition().style("height", 100)

如果我将其更改为...

d3.select("div").transition().style("height", "100px")

它再次起作用.转换前的原始值为... style("height",0),它以html内联样式的高度显示为"0px".

此更改在今天的版本中发生了吗?是否打算进行此更改?在d3中使用像这样的数字是否被认为是不好的做法?谢谢.

编辑
我在下面添加了一个示例. div1的高度不会过渡,因为它使用的是数字而不是带有px单位的字符串.

 d3.select("#div1").transition().style("height", 100)

d3.select("#div2").transition().style("height", "100px") 
 <div id="div1" style="background-color:purple;height=10px;width=100px"></div>
<div id="div2" style="background-color:red;height=10px;width=100px"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script> 

我在下面的v5.7中添加了一个正在运行的示例,您可以在其中看到两个转换都有效.我已经简化了我的原始示例.我必须在此示例中添加css以复制我在实际应用程序中看到的内容.现在看来,它与inline-flex风格有关,我不确定为什么.

 d3.select("#div1").transition().style("height", 100)

d3.select("#div2").transition().style("height", "100px") 
 #parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
} 
 <div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height=0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height=10px">    </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 

解决方案

是的,新的D3 v5.8确实具有新的插值器.如果您查看今天发布的D3 v5.8的发行说明,在撰写本文时为2019年),您将看到:

在这里,可以使用v5.8轻松地演示该问题,我们尝试在其中将"20px"插入到100(即从字符串到数字):

 const svg = d3.select("svg");
const rect = svg.append("rect")
  .attr("width", "20px")
  .attr("height", "20px")
rect.transition()
  .duration(10)
  .attr("width", 100)
  .on("end", function() {
    console.log(rect.attr("width"))
  }) 
 <script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg> 

如您所见,您会得到一个NaN

请注意,它不会在v5.7中发生:

 const svg = d3.select("svg");
const rect = svg.append("rect")
  .attr("width", "20px")
  .attr("height", "20px")
rect.transition()
  .duration(10)
  .attr("width", 100)
  .on("end", function() {
    console.log(rect.attr("width"))
  }) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg> 

无论如何,回答您的问题:

是的,这是(我不得不承认我有时这样做),但这与D3不相关:如果您将"20px"(字符串)作为初始状态,则应将"100px"(字符串)作为最终状态,而不是100(数字).这样可以使插值更清晰,更不易出错.

但是,这不是您的情况:您拥有处于初始状态和最终状态的数字.在您的情况下,即使您使用数字(如0)作为初始状态,吸气剂也将获得"0px"作为字符串.最后,值得一提的是,您的特定示例在v5.7和v5.8上均不起作用,因此建议您在问题中使用v5.7发布一个非常简单的示例.

编辑

根据要求,您使用工作示例编辑了问题,非常感谢.

关于示例#1,它也不能与D3 v5.7一起使用,这就是我的观点(您的特定示例在v5.7和v5.8上均不起作用" ).看看,没有紫色的div(两个高度均以0px开头):

 d3.select("#div1").transition().style("height", 100)
d3.select("#div2").transition().style("height", "100px") 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="div1" style="background-color:purple;height:0px;width:100px"></div>
<div id="div2" style="background-color:red;height:0px;width:100px"></div> 

我说过它也不能在D3 v5.7上运行,因为给我留下的印象是,在编写style("height", 0)之后,您以前已经使用D3设置了样式.

但是在第一个示例中,我们发现了一个问题:您以内联样式使用了=而不是:(这似乎可以解释奇怪的行为,请继续阅读).

关于第二个示例,即使对D3 v5.7使用了正确的内联样式语法,也无法使用

 d3.select("#div1").transition().style("height", 100)
d3.select("#div2").transition().style("height", "100px") 
 #parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
} 
 <div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height:0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height:10px"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 

因此,这里发生的只是inline-flex与不正确的内联样式(即,未正确将高度设置为0px)的不幸组合,这使紫色div扩展为父级.我们可以在下面的演示中看到这一点,在该示例中,我仅过渡了红色div :

 d3.select("#div2").transition().style("height", "100px") 
 #parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
} 
 <div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height=0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height=10px">    </div>
</div>
<script src="https://d3js.org/d3.v5.min.js"></script> 

I have d3 v5 code in my application that transitions the height of a div using a number. This no longer works since today's release of v5.8:

d3.select("div").transition().style("height", 100)

If I change it to...

d3.select("div").transition().style("height", "100px")

it works again. The original value before transition is ...style("height", 0) which shows as an html inline-style height of "0px".

Did this change happen in today's release? Was this change intended? Is it considered bad practice to use numbers like this in d3? Thanks.

EDIT
I've added an example below. The height for div1 doesn't transition because it's using a number instead of a string with px units.

d3.select("#div1").transition().style("height", 100)

d3.select("#div2").transition().style("height", "100px")
<div id="div1" style="background-color:purple;height=10px;width=100px"></div>
<div id="div2" style="background-color:red;height=10px;width=100px"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>

EDIT2: I've added a running example in v5.7 below where you can see that both transitions work. I had oversimplified my original example. I had to add the css in this example to replicate what I'm seeing in my actual application. It seems to now be related to the inline-flex style and I'm not sure why.

d3.select("#div1").transition().style("height", 100)

d3.select("#div2").transition().style("height", "100px")
#parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
}
<div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height=0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height=10px">    </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

解决方案

Yes, the new D3 v5.8 does have a new interpolator. If you look at the releases notes for D3 v5.8, released today (29/Jan/2019 at the time of writing), you'll see:

The problem can be easily demonstrated here, using v5.8, where we try to interpolate "20px" to 100 (that is, string to number):

const svg = d3.select("svg");
const rect = svg.append("rect")
  .attr("width", "20px")
  .attr("height", "20px")
rect.transition()
  .duration(10)
  .attr("width", 100)
  .on("end", function() {
    console.log(rect.attr("width"))
  })
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

As you can see, you'll get a NaN!

Note that it won't happen in v5.7:

const svg = d3.select("svg");
const rect = svg.append("rect")
  .attr("width", "20px")
  .attr("height", "20px")
rect.transition()
  .duration(10)
  .attr("width", 100)
  .on("end", function() {
    console.log(rect.attr("width"))
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

Anyway, answering your question:

Yes, it is (I have to confess I do that sometimes), but this is not D3 related: if you have "20px" (a string) as the initial state you should have "100px" (a string) as the final state, not 100 (a number). This makes the interpolation more clear and less error-prone.

This is not your case, though: you have numbers in both initial and final state. What's happening in your case is that, even if you use a number (like 0) as the initial state, the getter will get "0px", as a string. Finally, it's worth mentioning that your specific example doesn't work neither on v5.7 nor v5.8, so I'd suggest that you post a very simple working example using v5.7 in your question.

EDIT

As requested, you edited your question with working examples, thanks for that.

Regarding your example #1, it won't work with D3 v5.7 as well, that was my point above ("your specific example doesn't work neither on v5.7 nor v5.8"). Have a look, no purple div (both heights starting at 0px):

d3.select("#div1").transition().style("height", 100)
d3.select("#div2").transition().style("height", "100px")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="div1" style="background-color:purple;height:0px;width:100px"></div>
<div id="div2" style="background-color:red;height:0px;width:100px"></div>

I said that it won't work on D3 v5.7 as well because I was under the impression, after you write style("height", 0), that you had previously set the style using D3.

But here in your first example we find a problem: you're using = instead of : in the inline style (that seems to explain the weird behaviour, keep reading).

Regarding your second example, it doesn't work if you use the correct syntax for the inline style, even with D3 v5.7, have a look:

d3.select("#div1").transition().style("height", 100)
d3.select("#div2").transition().style("height", "100px")
#parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
}
<div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height:0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height:10px"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

So, what's happening here is just an unfortunate combination of inline-flex with an incorrect inline style (that is, not correctly setting the height to 0px), which made the purple div expanding to the parent. We can see that in the demo below, where I'm transitioning only the red div:

d3.select("#div2").transition().style("height", "100px")
#parent-div {
  width:100px;
  display:inline-flex;
}
.sub-div {
  width: 100%;
}
<div id="parent-div" style="position:absolute;top:10px;width:100px">
  <div id="div1" class="sub-div" style="background-color:purple;height=0px"></div>
  <div id="div2" class="sub-div" style="background-color:red;height=10px">    </div>
</div>
<script src="https://d3js.org/d3.v5.min.js"></script>

这篇关于使用数字时,d3 v5.8是否释放了样式的过渡?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-13 15:18