0

I am developing a graph editor using two.js (SVG canvas). In this app I need to drag nodes (circles). The Node has a shape (circle) and a label. The node is linked to other nodes by lines, and each line have its label.

Graph editor while moving a node

The idea is to when I drag the node (circle) I move with it its label, and I update the lines accordingly and I update the label angle and position accordingly. My need is to know how to use events to make my code using best practices, something like observer design pattern.

I mean When I move the Node (circle) it notifies the linked lines that they should update. For now I just put the update of the lines inside the move node function. Here is the code :

    function mousedown(e) { 
     document.getElementById('log1').textContent = 'offsetY:' + e.offsetY + ' - clientY:' + e.clientY;
     if (e.clientY < 25) return; // menu

     mouse.current.set(e.clientX, e.clientY);
     mouse.previous.copy(mouse.current);

     move.start.set(e.clientX, e.clientY);

     window.addEventListener('mousemove', mousemove, false);
     window.addEventListener('mouseup', mouseup, false);

     realMousePos = mouse.current.clone().subSelf(two.scene.translation).divideScalar(two.scene.scale);
}


    function mousemove(e) {
    mouse.current.set(e.clientX, e.clientY);
    if(!isDragging){
        isDragging = true;
    }

    var dx = mouse.current.x - mouse.previous.x;
    var dy = mouse.current.y - mouse.previous.y;

    // To Pan
    if (State !== 'MOVE'){
        zui.translateSurface(dx, dy);
    } else {
        // Move Selected Nodes
        Move_SelectedNodes(dx, dy); //========> (see below)
    }

    mouse.previous.copy(mouse.current);
}

Updating node_label and linked lines

function Move_SelectedNodes(dx, dy){
    var zoomScale = two.scene.scale;
    var rdx = dx/zoomScale;
    var rdy = dy/zoomScale; 

    var dep = {x: rdx, y:rdy};//dep: deplacement !!!

    for(let i = 0; i < selectedNodes.length; i++){
         var node = selectedNodes[i];
         var node_circle = node.circle;
         var node_label = node.label;

         node_circle.translation.addSelf(dep);
         node_label.translation.addSelf(dep);

         //Move line end
         for (iBr = 0; iBr < node.branches.length; iBr++){
         var ligne = node.branches[iBr].ligne;

              if (ligne.vertices[0].node_id == node_circle.node_id) {
                   ligne.vertices[0].addSelf(dep);
              } else if (ligne.vertices[1].node_id == node_circle.node_id){             
                   ligne.vertices[1].addSelf(dep);
              }

              //Move line label
              var edgeLabel = node.branches[iBr].label;
              var labelX = (ligne.vertices[0].x + ligne.vertices[1].x)/2;
              var labelY = (ligne.vertices[0].y + ligne.vertices[1].y)/2;       
              edgeLabel.translation.set(labelX, labelY);
              edgeLabel.rotation = angle(ligne.vertices[0], ligne.vertices[1]);         
          }
      }

      two.update();
 }

Here is the whole example in JSFiddle https://jsfiddle.net/hichem147/fdzn1u0x/ To use it :

(1) create nodes by adding nodes by clicking first [(+) Nodes]
(2) click on the canvas where you want to add a node
(3) add branches (lines) by clicking [Branche]
(4) click on the nodes you want to link with a line
(5) To move nodes you click on [select] then
(6) select one node or many using [ctrl]
(7) click [Move]
(8) Move the selected nodes
(9) to end click [Pan/Zoom] or [Select] button
Hichem CHTARA
  • 25
  • 1
  • 7

1 Answers1

0

Finally, I saw this tutorial on using raphaelJS for something like what I developed, with rectangle and a text in it that should move with the rectangle. And the author is using the same method as I originally used. So it seems, that there is no need to complicate things. Just get things done.

http://thewayofcoding.com/2016/09/using-raphael-the-javascript-graphics-library/

Hichem CHTARA
  • 25
  • 1
  • 7