2016-09-21 70 views
5

我正在使用d3.js v4。我目前正在實施程序化縮放。這Panning and Zooming Tutorial已經非常有幫助。我的縮放與滾動輪一起工作,但我想創建按鈕進行縮放。我知道縮放和平移有什麼必要,是翻譯[tx, ty]和比例因子k。我正在爲我的X軸使用時間刻度。我設法得到tx和比例因子k,在x軸上獲得p1 (point 1)p2(point 2)的像素值,然後使用這些值得到k(比例因子)。喜歡這樣:W/Programmatic Zoom v4

var k = 500/(xScale(p2) - xScale(p1)); //500 is desired pixel diff. between p1 and p2, and xScale is my d3.scaleTime() accessor function. 
// for this zoom i just want the first value and last value to be at scale difference of the entire width. 

然後,我計算出這個TX:

var tx = 0 - k * p1; 

然後饋入一個d3.zoomIdentity()和重新調整我的xdomain。我創建了一個縮小的按鈕。問題是當我放大,然後嘗試使用按鈕縮小,它縮小,但收縮的X軸。我似乎無法找出爲什麼它縮小了X軸,而不是正確縮小。

我的jsfiddle

https://jsfiddle.net/codekhalifah/Lmdfrho7/2/

我已經試過

我的代碼

後滾輪縮放應用運行此功能:

function zoomed() { 
     if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush 
var t = d3.event.transform; 
console.log(t); 
console.log(xScale.domain()); 
xScale.domain(t.rescaleX(x2).domain()); 
usageAreaPath.attr("d", area); 
usageLinePath.attr('d',line); 
weatherAreaPath.attr('d',weatherChart.area); 
focus.select(".axis--x").call(xAxis); 
focus.selectAll('.circle') 
    .attr('cx', function(d) { return xScale(getDate(d)); }) 
    .attr('cy', function(d) { return yScale(d.kWh); }) 
    .attr("transform", "translate(0," + 80 + ")"); 

     ... other non related items 
    } 

變焦正常工作,但放大,然後手動試圖放大正常位置,我想以後。 我的手動變焦按鈕功能

function programmaticZoom(){ 
var currDataSet = usageLinePath.data()[0], //current data set 
     currDataSetLength = currDataSet.length,//current data set length 
     x1 = currDataSet[0].usageTime, //getting first data item 
     x2 = currDataSet[currDataSetLength-1].usageTime, //2nd data item 
     x1px = xScale(moment(x1)), //Get current point 1 
     x2px = xScale(moment(x2)); // Get current point 2 

     // calculate scale factor 
     var k = width/(x2px - x1px); // get scale factor 
     var tx = 0 - k * x1px; // get tx 
     var t = d3.zoomIdentity.translate(tx).scale(k); //create zoom identity 

     xScale.domain(t.rescaleX(window.x2).domain()); 
     usageAreaPath.attr("d", area); 
     usageLinePath.attr('d',line); 
     weatherAreaPath.attr('d',weatherChart.area); 
     focus.select(".axis--x").call(xAxis); 
     focus.selectAll('.circle') 
      .attr('cx', function(d) { return xScale(getDate(d)); }) 
      .attr('cy', function(d) { return yScale(d.kWh); }) 
      .attr("transform", "translate(0," + 80 + ")"); 

} 
+0

只是要清楚;你想讓你的變焦按鈕始終放大回到默認的初始視圖? – Hamms

+0

@Hamms嗯,我想實際上能夠放大到不同的級別。這只是我的第一個測試級別。但在Timescale上,我想從幾個月的視圖縮放到周視圖,一天縮小到15分鐘。我的第一個測試級別是回到看到幾個月。 – inspired

+0

@Hamms有什麼想法? – inspired

回答

3

我一直在看這一會兒了,我得到了它排序工作,有一件事我想不通,但是你也許能因爲你似乎比我更熟悉d3。在您的programmaticZoom()函數中,我注意到tx是圖的起始位置的偏移量,而k是比例尺。利用這一點,我換了塊:

var k = width/(x2px - x1px); // get scale var tx = 0 - k * x1px; // get tx var t = d3.zoomIdentity.translate(tx).scale(k);

var k = 1; var t = d3.zoomIdentity.scale(k);

首先,當k = 1.0,圖形將適合在窗口完美。我相信將k設置爲原來的值的原因是錯誤的是,當您將k的值增加到k > 1.0時,它會將圖形的寬度拉伸到屏幕之外。圖表上的內容必須重新調整,以便儘可能在圖表上佔用儘可能多的空間,同時仍在屏幕範圍內。使用k < 1(這與width/(x2px - x1px);發生的情況相同),圖表縮小爲小於屏幕大小。像這樣重新調整隻會使圖形的內容在圖內佔據最大值,但由於圖形比屏幕小,因此它將被重新調整以適應縮小的圖形並且顯示爲比屏幕更小。

我擺脫了tx完全是因爲它抵消了圖表的起始位置。當圖形放大時,它的寬度被拉伸過屏幕。在這裏偏移是有意義的,因爲您需要使偏移等於您想要開始查看圖形的位置,並允許您不需要的部分保持離開屏幕。如果您一直縮小圖形,圖形爲屏幕大小的,所以偏移會導致圖形不在屏幕的開頭處開始,而是將其一部分從屏幕的開始處移開屏幕。在你的情況下,k已經縮小了圖形,偏移會導致縮小的圖形出現在屏幕中間。但是如果圖形沒有縮小,偏移量會將圖形的一部分從屏幕上移開。

通過改變,縮小按鈕出現工作,但仍然有問題。在zoomed()函數中,您設置了var t = d3.event.transform;d3.event.transform包含的值爲k, x, and y,當完全縮小時需要分別爲1, 0, and 0。但我不能在programmaticZoom()函數中更改這些值,因爲d3.event.transform只在觸發事件(特別是鼠標滾輪)後才存在。如果僅在單擊縮放按鈕時才能將這些值設置爲k = 1, x = 0, y = 0,則應該完全解決問題。

希望這有助於一些人,我對d3不是很熟悉,但是這應該可以解決您的大部分問題,並希望能夠告訴您發生了什麼問題。