如何确定两个d3刻度是否相等或者d3刻度是否已更改?

时间:2017-05-04 09:21:57

标签: javascript reactjs d3.js

我正在使用React和d3,我试图找出如何在比例变化时正确触发渲染。但是,很难可靠地检测秤是否已经改变。

从理论上讲,我可以考虑解决这个问题的两条路线。

我可以在每个渲染上重新生成比例,然后有一个可靠的方法来确定两个比例是否相同(例如比较它们的域,范围等)。但是仍然存在一些问题 - 例如,我实际上并不确定如何使用相同的域和范围来区分线性比例和对数比例。 (如果我尝试测试值 - 说域的中点 - 如果给出一个非数字刻度,它会崩溃。我可以避免这种情况,呃,'反向鸭子打字'全部d3&# 39;各种尺度,但这似乎非常繁琐,如果测试功能变得过于简洁,可能会导致性能下降。)

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

1 个答案:

答案 0 :(得分: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,而是比较整个函数更好的主意。正如comments section中指出的@altocumulus,某些尺度会返回相同的copy