d3.js на холсте, не может определить правильные координаты узла при использовании функции масштабирования и перетаскивания

Я пытаюсь визуализировать данные JSON, используя d3 v4 и холст. Я сталкиваюсь с некоторыми трудностями при реализации масштабирования, панорамирования и перетаскивания. Хотя код дает практически все желаемые результаты, после масштабирования при щелчке узла он отображается в другом месте. Я предполагаю, что это потому, что мне не удается определить правильные координаты для узла после преобразования.

Вот выдержки из кода:

var canvas=document.querySelector("canvas"),
context=canvas.getContext("2d"),
width=canvas.width,
height=canvas.height;

context.clearRect(0,0,width,height);
context.fillStyle=" #566573";
context.fillRect(0,0,width,height); 

var color = d3.scaleOrdinal(d3.schemeCategory20);    

d3.json('data.do', function(error,graph) {
var radius=3;
var simulation = d3.forceSimulation() 
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.alpha(0.5)
.alphaDecay(0.03)
.velocityDecay(.4)
.force("y", d3.forceY(height/2).strength(.020))
.force("collision", d3.forceCollide().radius(function(d) {      return  radius+2;   })) 


var transform=d3.zoomIdentity;
d3.select(canvas)
.call(d3.drag().subject(dragsubject).on("start",dragstarted).on("drag", dragged))
.call(d3.zoom().scaleExtent([1 / 10, 8]).on("zoom", zoomed)).on("dblclick.zoom",null)
.on('click',function(){console.log("clicked");})

function zoomed() {
  transform = d3.event.transform;
  simulationUpdate();
}


function dragsubject() {
    var i,
    x = transform.invertX(d3.event.x),
    y = transform.invertY(d3.event.y),      
    dx,
    dy;

    for (i = graph.points.length - 1; i >= 0; --i) {
      node = graph.points[i];
      dx = x - node.x;
      dy = y - node.y;
      if (dx * dx + dy * dy < radius * radius) {
        node.x = transform.applyX(node.x);
        node.y = transform.applyY(node.y);
        return node;
      }
    }
}
function dragstarted() {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d3.event.subject.fx = transform.invertX(d3.event.x);
    d3.event.subject.fy = transform.invertY(d3.event.y);
  }

 function dragged() {
  d3.event.subject.fx = transform.invertX(d3.event.x);
  d3.event.subject.fy = transform.invertY(d3.event.y);
 }

simulation
  .nodes(graph.points)
  .on("tick", simulationUpdate);

simulation.force("link")
  .links(graph.plinks);

function simulationUpdate(){
  console.log("simulationupdate");
  context.save();
  context.clearRect(0, 0, width, height);

  context.fillStyle=" #2a2c2d ";
  context.fillRect(0,0,width,height);
  context.translate(transform.x, transform.y);
  context.scale(transform.k, transform.k);

  graph.plinks.forEach(function(d) {
      context.beginPath();
        context.moveTo(d.source.x, d.source.y);
        context.lineTo(d.target.x, d.target.y);
        context.strokeStyle = "#335d6c";
        context.stroke();
    });


    graph.points.forEach(function(d, i) {
      context.beginPath();          
      context.moveTo(d.x+radius,d.y);
      context.arc(d.x,d.y, radius, 0, 2 * Math.PI, true);
      context.fillStyle=color(d.group);
      context.fill();
      context.strokeStyle = "#fff";
      context.stroke();
    });

    context.restore();
}
});

JSON-объект 'graph' выглядит следующим образом:

{
"plinks":[ 
{"source":"source1","target":"target1","value":"1"},
{"source":"source2","target":"target2","value":"0"},
.
.
],
"points":[
{"group":0,"id":"source1"},
{"group":3,"id":"source2"},
.
.
]
}

Функции увеличения и уменьшения и перетаскивания работают нормально. Ведение журнала консоли сообщает мне, что при нажатии на узел вызываются методы dragsubject, dragstarted, clicked и Simulationupdate. Я не мог выяснить, что именно вызывает узел, чтобы иметь разные координаты после щелчка мышью.

Ссылка: https://bl.ocks.org/jodyphelan/5dc989637045a0f48418101423378fbd и многие другие Bl.ocks.

Оцените любую помощь заранее. Спасибо.

0 ответов

Другие вопросы по тегам