2017-05-04 28 views
3

我正在使用React和d3,並試圖找出如何在比例更改時正確觸發呈現。但是,要可靠地檢測秤是否發生了變化是相當困難的。如何確定兩個d3刻度是否相等或d3刻度是否已更改?

理論上,我可以想到兩條路線來解決這個問題。

我可以在每個渲染上重新生成比例尺,然後確定兩個比例是否相同(例如比較它們的域,範圍等)。但是仍然存在一些問題 - 例如,我實際上並不確定如何區分具有相同域和範圍的線性比例尺和對數比例尺。 (如果我嘗試一個測試值 - 比如域的中點 - 它會在給定非數字尺度的時候崩潰,我可以通過呃,「反向鴨子鍵入」所有d3的不同尺度來避免這種情況,但這似乎是如果測試函數變得過於簡單,則會非常單調乏味,並且可能會導致性能下降。)

另一種解決方案是在整個渲染過程中保持一致的縮放對象,但以某種方式獲取縮放以觸發渲染,如果其任何屬性改變。我認爲這最終會與第一種選擇相同,但也許d3中有一些我不知道的技巧可以讓它更容易?

+0

我認爲你的問題的最佳答案取決於你是否在渲染方法中使用d3,或者是否在其他生命週期方法中使用d3選擇器。 –

+0

如何使用一些實用變量來確定您定義的點的縮放類型,例如'var isLinear = true;'並在您更改縮放比例時對其進行修改。 – mtx

回答

1

(警告:這是一個非常哈克解決方案,知道你有什麼樣的規模。如果你不舒服,請讓我知道,我會刪除它。)

每檯秤在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

+0

如果您使用縮小版本,雖然。對我而言,這感覺有點過分*哈克*。 – altocumulus

+0

@altocumulus不,它不會中斷,它與縮小版本的工作方式相同,因爲*函數*不同,正如您在代碼片段中看到的一樣。我知道這太hacky,**非常意味着:達到最高程度。 –

+0

我的不好,我只讀了第一部分,並認爲你是從字面上尋找這個名字。我遵循了一個類似的路徑,它不涉及比較'.copy()',而是比較了整個函數,即'scale1.toString()=== scale2.toString()'。但這只是一個品味問題。 – altocumulus