2017-03-19 19 views
3

我發現zooming with minimap這個很好的例子,但它是寫在舊版本V3。我幾乎將其轉換爲v4,但d3.event存在問題。在第3版中,d3.event似乎在調用縮放的兩個元素之間共享縮放參數。所以,如果我縮放到主畫布,然後在小地圖上的畫布 - 在d3.event將有主畫布變焦d3.event的最後一個刻度值,它會與變焦不斷理所應當。但在v4中,這兩個d3縮放事件在某種程度上具有單獨的縮放或平移值。如文檔中所示:d3.js v4 minimap或如何在兩個元素上共享縮放?

縮放行爲將縮放狀態存儲在應用了縮放行爲的元素上,而不是縮放行爲本身。這是因爲縮放行爲可以同時應用於多個元素,並且每個元素可以獨立縮放。

但是,這留下了一個問題,我可以如何在兩個元素上共享一個縮放事件?

回答

3

編輯:

大也感謝比爾白,誰在同一個線程張貼了他的最新文章 - D3 MINIMAP V4 UPDATE。該文章實際上是我在我的問題中發佈的示例的更新。


問題的答案可以找到here

@mbostock和藹地回答一個問題線程我的問題。我還找到了另一種解決方案我成功地將他的代碼中的一些邏輯和公式直接實現到了我的縮放處理器中。它像一個魅力。

所以這是從V3到V4更新的縮放處理:未列入翻譯boundery檢查:

注。

// .... 

var scale = 1; 
var minScale = .5; 
var maxScale = 7.5; 
var translation = [0, 0]; 

// .... 

// Used for both main canvas and minimap zoom 
var zoom = d3.zoom() 
    .on('zoom', zoomHandler); 

function zoomHandler(newScale) { 
    var prevScale = scale; 
    var previousTranslation = getXYFromTranslate(panCanvas.attr('transform')); 
    var isZoomEvent = d3.event && d3.event.sourceEvent.deltaY; 
    var isDragEvent = d3.event && (d3.event.sourceEvent.movementX || d3.event.sourceEvent.movementY); 

    if (isZoomEvent) { 
     scale = calculateNewScale(prevScale, d3.event.sourceEvent); 
     scale = checkScaleBounderies(scale); 

     var mousePosition = d3.mouse(this); 

     // Based on d3.js zoom algorythm 
     translation[0] = mousePosition[0] - ((mousePosition[0] - previousTranslation[0])/prevScale) * scale; 
     translation[1] = mousePosition[1] - ((mousePosition[1] - previousTranslation[1])/prevScale) * scale; 
    } else if (isDragEvent) { 
     translation[0] = previousTranslation[0] + d3.event.sourceEvent.movementX; 
     translation[1] = previousTranslation[1] + d3.event.sourceEvent.movementY; 
    } else if (newScale) { 
     scale = newScale; 
    } 

    // Apply the new dimensions to the main canvas 
    panCanvas.attr('transform', 'translate(' + translation + ') scale(' + scale + ')'); 

    // Apply the new dimensions to the minimap 
    minimap.scale(scale).render(); 
} 

// Calculate the new scale value based on d3.js zoom formula 
function calculateNewScale(prevScale, event) { 
    return prevScale * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1)/500); 
} 

// Check if scale has reached max or min 
function checkScaleBounderies(newScale) { 
    return Math.max(minScale, Math.min(maxScale, newScale)); 
} 

//.... 

function getXYFromTranslate(transform) { 
    // Create a dummy g for calculation purposes only. This will never 
    // be appended to the DOM and will be discarded once this function 
    // returns. 
    var g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); 

    // Set the transform attribute to the provided string value. 
    g.setAttributeNS(null, 'transform', transform); 

    // consolidate the SVGTransformList containing all transformations 
    // to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get 
    // its SVGMatrix. 
    var matrix = g.transform.baseVal.consolidate().matrix; 

    // As per definition values e and f are the ones for the translation. 
    return [matrix.e, matrix.f]; 
}