【问题标题】:How do I determine if two d3 scales are equivalent OR if a d3 scale has changed?如何确定两个 d3 量表是否相等或 d3 量表是否已更改?
【发布时间】:2017-05-04 09:21:56
【问题描述】:

我正在将 React 与 d3 一起使用,并且我正在尝试研究如何在比例更改时正确触发渲染。但是,要可靠地检测尺度是否发生了变化是相当困难的。

理论上,我可以想到两种解决问题的方法。

我可以在每次渲染时重新生成比例,然后有一种可靠的方法来确定两个比例是否相同(例如比较它们的域、范围等)。但是仍然存在一些问题——例如,我实际上并不确定如何区分具有相同域和范围的线性刻度和对数刻度。 (如果我尝试一个测试值——比如域的中点——如果给定一个非数字比例,它会崩溃。我可以通过,呃,'reverse-duck-typing'所有 d3 的各种比例来避免这种情况,但这似乎非常繁琐,如果测试功能变得过于简单,可能会降低性能。)

另一种解决方案是在渲染中保持一致的缩放对象,但如果其任何属性发生更改,则以某种方式获取缩放以触发渲染。我认为这最终会与第一个选项中的相同,但也许 d3 中有一些我不知道的技巧使它更容易?

【问题讨论】:

  • 我认为您问题的最佳答案取决于您是在渲染方法中使用 d3,还是在其他生命周期方法中使用 d3 选择器。
  • 如何使用一些实用变量来确定您定义它的点的比例类型,例如var isLinear =true;,并在您更改比例时修改它。..

标签: javascript reactjs d3.js


【解决方案1】:

(警告:这是一个 非常 hacky 的解决方案,用于了解您拥有什么样的规模。如果您不满意,请告诉我,我会删除它)

D3 v4.x 中的每个比例都有一个copy 函数,它公开了比例的类型。例如,这是线性刻度的copy 函数:

scale.copy = function() {
    return copy(scale, linear());
};

这是波段刻度的copy 函数:

scale.copy = function() {
    return band()
        .domain(domain())
        .range(range)
        .round(round)
        .paddingInner(paddingInner)
        .paddingOuter(paddingOuter)
        .align(align);
};

等等……

如您所见,刻度的类型始终存在于返回值中(如果您使用的是 D3 的非缩小版本)。

因此,我们可以使用它来比较尺度(在比较域和范围的基础上,就像您现在所做的那样)。这是一个例子:

var scale1 = d3.scaleBand();
  
var scale2 = d3.scaleLinear();
  
var scale3 = d3.scaleLinear();
  
console.log("Is scale1 the same of scale2? " + (scale1.copy.toString() === scale2.copy.toString()))
console.log("Is scale1 the same of scale3? " + (scale1.copy.toString() === scale3.copy.toString()))
console.log("Is scale2 the same of scale3? " + (scale2.copy.toString() === scale3.copy.toString()))
<script src="https://d3js.org/d3.v4.min.js"></script>

这可用于测试具有相同域和范围的不同尺度(正如您在问题中所问的那样):

var scale1 = d3.scaleLinear()
  .domain([10, 20])
  .range([10, 20]);

var scale2 = d3.scaleLog()
  .domain([10, 20])
  .range([10, 20]);

console.log("Is scale1 the same of scale2? " + (scale1.copy.toString() === scale2.copy.toString()))
<script src="https://d3js.org/d3.v4.min.js"></script>

编辑:与其比较copy,不如比较整个函数。正如@altocumulus 在comments section 中指出的那样,一些秤返回相同的copy

【讨论】:

  • 不过,如果您使用的是缩小版,则会中断。对我来说,这感觉有点太hacky了。
  • @altocumulus 不,它不会中断,它与缩小版本的工作方式相同,因为 功能 不同,正如您在 sn-ps 中看到的那样.我知道这太hacky了,非常的意思就是:达到最高程度。
  • 我的错,我只阅读了第一部分,并认为您正在寻找字面意义上的名字。我遵循了类似的路径,它不涉及比较.copy(),而是比较了整个函数,即scale1.toString() === scale2.toString()。但这只是口味问题。
  • 是的,您可以使用scale.toString()scale.copy.toString()。完全披露:我使用copy 是因为我试图提取return 中的比例名称......然后,无聊和疲倦,我决定使用简单的toString() 来写这个答案。
  • 在深入研究之后,我的发现是,你真的应该比较整个函数,因为scalePowscaleSqrt 以及scaleTimescaleUtc 共享相同的复制方法。
猜你喜欢
  • 2011-03-26
  • 2021-05-23
  • 2011-07-10
  • 2016-01-04
  • 2016-03-13
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多