2012-11-06 32 views
4

當我用鼠標放大,下面的函數attacted爲「myZoom」將被執行:D3:火變焦事件(或模擬變焦事件)

myZoom.on('zoom', function() { 

    someElement.attr('transform', 'translate(' + d3.event.translate[0] + ',' + d3.event.translate[1] + ') scale(' + d3.event.scale + ')'); 

.... 
// redraw axes, which should stay where they are at. 
.... 

} 

爲了模擬變焦而不鼠標或一些其他定點設備,我可以改變上面的屬性'transform'的值。簡單。

但問題是在這個函數中,我實際上重繪了軸,其尺度會自動重新計算。請參閱本官方文檔從D3:

zoom.y([Y])

指定的y標尺,其域名應該縮放時自動調整 。如果未指定,則返回當前的y比例,其中 默認爲空。如果比例域以編程方式進行修改,則應將其重新分配給縮放行爲 。

我需要以編程方式縮放(也許使用縮放按鈕)。我如何觸發縮放事件,以便自動重新計算我的座標軸的比例?

+0

即將發佈的d3(3.0版)具有一些新的縮放功能。這可能會幫助你適應你的情況。請參閱:https://github.com/mbostock/d3/commit/f1c87d7e3a02074287326faa46e748543e25a219 – nautat

+0

你見過[編程泛+放大示例](http://bl.ocks.org/3892928)嗎? – mbostock

+0

感謝您的回覆。 @mbostock:在你的例子中,我們只是回到原始域: x.domain([ - width/2,width/2]); y.domain([ - height/2,height/2]); 但我想放大到一些任意級別。 – user1592714

回答

2

我結束了自己計算新的縮放級別的新域。有了這個新的領域,我可以重繪兩個y軸。對於有同樣問題的人,我發佈我的代碼。這對我的項目非常具體,所以可能很難理解。只是爲了你的興趣。

wr.zoomSim = function(sNew) { 

    var s = wr.zoom.scale(), 
     tx = wr.zoom.translate()[0], 
     ty = wr.zoom.translate()[1], 
     sReal = sNew/s, 
     dtx = wr.width/2 * (1 - sReal), 
     dty = wr.height/2 * (1 - sReal), 
     txNew = sReal * tx + dtx, 
     tyNew = sReal * ty + dty, 

     a = wr.scaleYBZoom.domain()[0], 
     b = wr.scaleYBZoom.domain()[1], 
     c = wr.scaleYBZoom.range()[0], 
     d = wr.scaleYBZoom.range()[1], 
     r = (b-a)/(d-c); 

    wr.scaleYBZoom.domain([a + r * ((c - dty)/sReal - c), a + r * ((d - dty)/sReal - c)]); 

    wr.zoom.scale(sNew); 
    wr.zoom.translate([txNew, tyNew]); 

    wr.svg2.select('g#bar') 
      .attr('transform', 'translate(' + txNew + ',' + tyNew + ') scale(' + sNew + ')'); 

    wr.svg2.select('g#axisl') 
      .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('left')) 
     .selectAll('line.tick') 
      .attr('x2', wr.width - wr.bar.left - wr.bar.right + 2 * wr.padding); 
    wr.svg2.select('g#axisr') 
      .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('right')) 
     .selectAll('line') 
      .remove(); 

}; 
+0

非常好,最頂級的代碼幫了我很多。 –

6

由於D3縮放與鼠標事件密切相關,因此在D3庫中編程縮放似乎是一項艱鉅的任務。程序縮放的常見實例是使用滑塊控件放大或縮小。令人驚訝的是,我找不到一個如何使用滑塊控件進行D3縮放工作的實例。在投入了一些時間和精力之後,我開發了這個工作演示,可以在這裏找到D3SliderZoom。關鍵點是使用滑塊引發的縮放值來更改嵌入到「元素」元素中的「SVGElement」元素的transform屬性。

function zoomWithSlider(scale) { 
    var svg = d3.select("body").select("svg"); 
    var container = svg.select("g"); 
    var h = svg.attr("height"), w = svg.attr("width"); 

    // Note: works only on the <g> element and not on the <svg> element 
    // which is a common mistake 
    container.attr("transform", 
      "translate(" + w/2 + ", " + h/2 + ") " + 
      "scale(" + scale + ") " + 
      "translate(" + (-w/2) + ", " + (-h/2) + ")"); 

}

然後,此方法必須從滑塊的變化事件調用,如下所示。

$(function() { 
$("#slider-vertical").slider({ 
    orientation: "vertical", 
    range: "min", 
    min: 1000, 
    max: 10000, 
    value: 1000, 
    slide: function(event, ui) { 
     zoomWithSlider(ui.value/1000); 
    } 
}); 

});

該解決方案比生成僞鼠標滾動事件更優雅。

+0

謝謝你。任何人都可以用laymans的詞彙來解釋2次轉換的做法(w/2,-w/2)嗎?它也似乎在鼠標縮放事件中工作,以保持縮放從鼠標位置的中心,我也喜歡。 – automagic

+1

這個變換可以讓你從假設座標轉換到真實座標......在你的腦海中,你可以假設你的電腦屏幕的中心是原點(0,0),y軸的值增加了......但實際上左上角是(0,0)和y值向下增加...因此變換(w/2,-h/2)是必要的轉換你的心智計算的數字和真正的... – Debasis

1

不幸的是@ Debasis的答案對我來說並不奏效,因爲我想用zoom behavior來達到這個效果,我已經在使用我的force layout。之後絕望的兩天,我終於找到了在這個線程解決方案:

https://groups.google.com/forum/#!msg/d3-js/qu4lX5mpvWY/MnnRMLz_cnUJ

function programmaticZoom ($svg, $zoomContainer, zoomBehavior, factor) { 

    var width = $svg.attr('width'); 
    var height = $svg.attr('height'); 

    var newScale = zoomBehavior.scale() * factor; 
    var newX = (zoomBehavior.translate()[0] - width/2) * factor + width/2; 
    var newY = (zoomBehavior.translate()[1] - height/2) * factor + height/2; 

    zoomBehavior 
     .scale(newScale) 
     .translate([newX,newY]) 
     .event($zoomContainer); 
} 
+0

這實際上好多了,因爲它確實會改變縮放行爲的內部狀態,所以如果您可以以一致的方式組合編程縮放和鼠標滾輪縮放。 – Nytux

0

我通過使用zoomListener的這樣做。在簡單的步驟行之有效對我來說:

  1. 定義zoomListener: VAR zoomListener = d3.behavior.zoom();
  2. 調用縮放監聽器 d3.select(the-element-that-you-need-zoom-on).call(zoomListener);
  3. 確定您的縮放步驟。我採取了0.1的步驟。 (使用1.1進行放大,使用0.9進行縮小)
  4. 與當前縮放比例相乘 var newScale = zoomListener.scale()* step;
  5. 設置新的比例值 zoomListener.scale(newScale);