2017-03-23 69 views
0

我已經實現了一個使用畫布的網絡圖,使用this example (Force Layout with Canvas),功能爲drag (Circle Dragging II)zoom (Canvas geometric zooming)全部更新到V4。D3.js - 用畫布縮放網絡圖,然後拖動節點

的問題是,當我縮放或拖動畫布和應用:在某種程度上沒有相應更新

canvas.translate(d3.event.translate[0], d3.event.translate[1]); 
canvas.scale(d3.event.scale, d3.event.scale); 

節點對象。他們的canvas.restore();之前被畫得很好,但是當我嘗試目標節點使用鼠標:

function getDragSubject() { 
    for (var i = nodes.length - 1, node, x, y; i >= 0; --i) { 
     node = nodes[i]; 
     x = node.x - d3.event.x; 
     y = node.y - d3.event.y; 

     if (x * x + y * y < radius * radius) return node; 
    } 
} 

什麼也沒有發生。

我最終會做這樣的:

function getDragSubject() { 
    for (var i = nodes.length - 1, node, x, y; i >= 0; --i) { 
     node = nodes[i]; 
     x = node.x * scale + translation[0] - d3.event.x; 
     y = node.y * scale + translation[1] - d3.event.y; 

     if (x * x + y * y < (radius * scale) * (radius * scale)) return node; 
    } 
} 

保存和添加翻譯和規模,使我能拖帆布/變焦後適當選擇它們,但它不似乎是正確的方式給我。另外,當我拖動後重畫畫布時,我遇到了節點正確定位的問題。

function draw() { 
    // draw links 
    context.strokeStyle = '#ccc'; 
    context.beginPath(); 
    links.forEach(function(d) { 
     context.moveTo(d.source.x * scale + translation[0], d.source.y * scale + translation[1]); 
     context.lineTo(d.target.x * scale + translation[0], d.target.y * scale + translation[1]); 
    }); 
    context.stroke(); 

    // draw nodes 
    context.fillStyle = 'steelblue'; 
    context.beginPath(); 
    nodes.forEach(function(d) { 
     context.moveTo(d.x * scale + translation[0], d.y * scale + translation[1]); 
     context.arc(d.x * scale + translation[0], d.y * scale + translation[1], radius * scale, 0, 2 * Math.PI); 
    }); 
    context.fill(); 
} 

無論如何,這看起來不正確。

任何人有關於改進或修改的建議?

回答

1

所以我想解決方案可以在這篇文章中找到:Mouse coordinates don't match after Scaling and Panning canvas。繪圖功能不應該更新 - 保持與以前一樣。

function draw() { 
    // draw links 
    context.strokeStyle = '#ccc'; 
    context.beginPath(); 
    links.forEach(function(d) { 
     context.moveTo(d.source.x, d.source.y); 
     context.lineTo(d.target.x, d.target.y); 
    }); 
    context.stroke(); 

    // draw nodes 
    context.fillStyle = 'steelblue'; 
    context.beginPath(); 
    nodes.forEach(function(d) { 
     context.moveTo(d.x, d.y); 
     context.arc(d.x, d.y, radius, 0, 2 * Math.PI); 
    }); 
    context.fill(); 
} 

拖動處理函數應更新:

var rect = canvas.getBoundingClientRect(); 

function onDrag() { 
    d3.event.subject.fx = ((d3.event.sourceEvent.pageX - rect.left) - translation[0])/scale; 
    d3.event.subject.fy = ((d3.event.sourceEvent.pageY - rect.top) - translation[1])/scale; 
}