簡體   English   中英

如何使用d3畫布渲染器添加鼠標事件以強制執行有向圖?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM