[英]how to add mouse events to force directed graph using the d3 canvas renderer?
其他所有示例都帶有svg.append()的鼠標事件。...我不知道在畫布渲染器中“進入”哪里獲取弧並添加.on('click', function(){})
在v4樣式中。 我想單擊以獲得d
的值。 在此示例中,我應在哪里添加處理程序? 我了解此示例下方的舊方法。
可能會進行這項工作嗎? d3.select(canvas).call(d3.mouse()).on("click", ...)
鏈接到工作示例
var links = d3.range(nodes.length - 1).map(function(i) {
return {
source: Math.floor(Math.sqrt(i)),
target: i + 1
};
});
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody())
.force("link", d3.forceLink(links).distance(20).strength(1))
.force("x", d3.forceX())
.force("y", d3.forceY())
.on("tick", ticked);
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function ticked() {
context.clearRect(0, 0, width, height);
context.save();
context.translate(width / 2, height / 2);
context.beginPath();
links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
nodes.forEach(drawNode);
context.fill();
context.strokeStyle = "#fff";
context.stroke();
context.restore();
}
function dragsubject() {
return simulation.find(d3.event.x - width / 2, d3.event.y - height / 2);
}
function dragstarted() {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d3.event.subject.fx = d3.event.subject.x;
d3.event.subject.fy = d3.event.subject.y;
}
function dragged() {
d3.event.subject.fx = d3.event.x;
d3.event.subject.fy = d3.event.y;
}
function dragended() {
if (!d3.event.active) simulation.alphaTarget(0);
d3.event.subject.fx = null;
d3.event.subject.fy = null;
}
function drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}
function drawNode(d) {
context.moveTo(d.x + 3, d.y);
context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
}
舊路
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 8)
.attr("fill", function(d) { return color(d.group); })
.on("click", togglenode)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
在D3 v4.x中,您添加單擊事件的方式與在v3.x中幾乎相同:
selection.on("click", function(d){
//do whatever you want with the datum
});
您所遇到的問題不是v3還是v4,這不是您共享的代碼中的問題。 該代碼的問題在於它使用HTML canvas而不是SVG來呈現dataviz。
與SVG不同,canvas沒有元素的節點樹。 您不能“選擇某些內容”,也不能為其添加事件處理程序。
將畫布視為光柵圖像,例如BMP或JPEG。 您可以找到單擊的x和y位置,甚至可以找到該像素的顏色,但是您無法選擇給定的節點元素,因為canvas沒有。
例如,請查看Nadieh Bremer的本教程,以了解使用HTML canvas時獲得用戶單擊的圓圈有多復雜。
由於我使用了畫布渲染器,因此我只是在示例中作弊並使用了d3 dragstart事件。 我想知道有辦法做到這一點。
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d3.event.subject.fx = d3.event.subject.x;
d3.event.subject.fy = d3.event.subject.y;
//broadcast the selection to parent
emitter.emit( d3.event.subject );
}
雙擊擴展FlavorScape的功能
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject)
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var clickDate = new Date();
var difference_ms;
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d3.event.subject.fx = d3.event.subject.x;
d3.event.subject.fy = d3.event.subject.y;
difference_ms = (new Date()).getTime() - clickDate.getTime();
clickDate = new Date();
//if clicks less than 200ms apart (double click)
if(difference_ms < 200)
console.log( d3.event.subject );
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.