2013-08-28 21 views
2

我們試圖在D3中創建的地圖頂部實現縮放按鈕 - 本質上它是在Google地圖上工作的。縮放事件可以使用d3js:使用視圖端口中心縮放焦點

d3ZoomBehavior.scale(myNewScale); 
d3ZoomBehavior.event(myContainer); 

分派並且地圖將使用視圖的當前轉換進行縮放。如果使用變焦按鈕,焦點(變焦中心)不再是平移,而是視口的中心。對於使用滾輪進行縮放,我們可以選擇使用zoom.center - 但在調度自己的事件時,這顯然不起作用。

我很困惑如何計算下一個轉換,考慮新的縮放因子和視口中心。

鑑於我知道當前比例尺,下一個比例尺,當前翻譯和地圖視圖端口的尺寸,我如何計算下一個翻譯,以便視口的中心不會改變?

+0

mbostock現在有專注於這裏的中心變焦按鈕的例子(四月9,2015):http://bl.ocks.org/mbostock/7ec977c95910dd026812 – airwwwave

回答

4

我發現這在實踐中很難做到。我採取的方法是使用here來簡單地創建一個鼠標事件,當使用縮放按鈕時觸發縮放。該事件創建在地圖的中心。

下面是相關代碼:

.on("click", function() { 
       var evt = document.createEvent("MouseEvents"); 
       evt.initMouseEvent(
        'dblclick', // in DOMString typeArg, 
        true, // in boolean canBubbleArg, 
        true, // in boolean cancelableArg, 
        window,// in views::AbstractView viewArg, 
        120, // in long detailArg, 
        width/2,  // in long screenXArg, 
        height/2,  // in long screenYArg, 
        width/2,  // in long clientXArg, 
        height/2,  // in long clientYArg, 
        0,  // in boolean ctrlKeyArg, 
        0,  // in boolean altKeyArg, 
        (by > 0 ? 0 : 1),  // in boolean shiftKeyArg, 
        0,  // in boolean metaKeyArg, 
        0,  // in unsigned short buttonArg, 
        null // in EventTarget relatedTargetArg 
       ); 
       this.dispatchEvent(evt); 
      }); 

整個事情是一個黑客位,但它在實踐中的工作,我已經發現了這個更容易,而不是計算每個偏移/變焦正確中心。

11

我最近不得不做同樣的事情,我在這裏有一個工作示例http://bl.ocks.org/linssen/7352810。本質上,它使用補間平滑縮放到所需的目標比例,並通過計算放大到中心後所需的差異進行平移。

我在下面列出了它的要點,但它可能值得看看the working example以獲得完整的效果。

HTML

<button id="zoom_in">+</button> 
<button id="zoom_out">-</button> 

JS

var zoom = d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoomed); 

function zoomed() { 
    svg.attr("transform", 
     "translate(" + zoom.translate() + ")" + 
     "scale(" + zoom.scale() + ")" 
    ); 
} 

function interpolateZoom (translate, scale) { 
    var self = this; 
    return d3.transition().duration(350).tween("zoom", function() { 
     var iTranslate = d3.interpolate(zoom.translate(), translate), 
      iScale = d3.interpolate(zoom.scale(), scale); 
     return function (t) { 
      zoom 
       .scale(iScale(t)) 
       .translate(iTranslate(t)); 
      zoomed(); 
     }; 
    }); 
} 

function zoomClick() { 
    var clicked = d3.event.target, 
     direction = 1, 
     factor = 0.2, 
     target_zoom = 1, 
     center = [width/2, height/2], 
     extent = zoom.scaleExtent(), 
     translate = zoom.translate(), 
     translate0 = [], 
     l = [], 
     view = {x: translate[0], y: translate[1], k: zoom.scale()}; 

    d3.event.preventDefault(); 
    direction = (this.id === 'zoom_in') ? 1 : -1; 
    target_zoom = zoom.scale() * (1 + factor * direction); 

    if (target_zoom < extent[0] || target_zoom > extent[1]) { return false; } 

    translate0 = [(center[0] - view.x)/view.k, (center[1] - view.y)/view.k]; 
    view.k = target_zoom; 
    l = [translate0[0] * view.k + view.x, translate0[1] * view.k + view.y]; 

    view.x += center[0] - l[0]; 
    view.y += center[1] - l[1]; 

    interpolateZoom([view.x, view.y], view.k); 
} 

d3.selectAll('button').on('click', zoomClick); 
+0

嘿威爾,你可以看看這個問題,它是基於你的實施,但與d3版本4,http://stackoverflow.com/questions/39932579/d3-js-zoom-on-click-event –

+0

看起來像你在臨時解決它,@ VladyslavBabenko? – Wil

+0

是啊,謝謝,它並不是那麼明顯,v4 api相當困惑。我可以實施與V4,也可以運行你的例子) –

8

一個更簡潔的版本威爾的解決方案:

var vis = d3.select('.vis'); 
    var zoom = d3.behavior.zoom()... 
    var width = .., height = ..; 

    function zoomByFactor(factor) { 
    var scale = zoom.scale(); 
    var extent = zoom.scaleExtent(); 
    var newScale = scale * factor; 
    if (extent[0] <= newScale && newScale <= extent[1]) { 
     var t = zoom.translate(); 
     var c = [width/2, height/2]; 
     zoom 
     .scale(newScale) 
     .translate(
      [c[0] + (t[0] - c[0])/scale * newScale, 
      c[1] + (t[1] - c[1])/scale * newScale]) 
     .event(vis.transition().duration(350)); 
    } 
    }; 

    function zoomIn() { zoomByFactor(1.2); } 
    function zoomOut() { zoomByFactor(0.8); } 
+0

伊利亞,你可以看看這個問題http://stackoverflow.com/questions/39932579/d3-js-zoom-on-click-event,它也一樣但是使用d3版本4 ...謝謝 –