Search code examples
javascriptcytoscape.js

On a Cytoscape.js graph, how to get the coordinates of the edge's terminal nodes by clicking it


On a Cytoscape graph that all the nodes are draggable and edges clickable, I want to click an edge connecting 2 particular nodes and access the (x,y) coordinates of the source and target nodes for some computation.

Here is the working code that one can run and click the edge (line connecting 2 nodes) and get some response.

var cy = cytoscape({
  container: document.getElementById("cy"),

  elements: {
    nodes: [{
        data: {
          id: "UK",
          name: "UK"
        },
        position: {
          x: 100,
          y: 100
        },
        classes: "text_UK"
      },
      {
        data: {
          id: "germany",
          name: "Germany"
        },
        position: {
          x: 270,
          y: 340
        },
        classes: "germany"
      }
    ],

    edges: [

      {
        data: {
          id: "UK2DE",
          source: "UK",
          target: "germany",
          label: "UK_DE"
        }
      }

    ]
  },

  style: [{
      selector: "node",
      style: {
        "background-color": "#bbbbbb",
        label: "data(name)",
        width: 60,
        height: 60,
        opacity: 1.0
      }
    },

    {
      selector: "edge",
      style: {
        label: "data(label)",
        width: 3,
        "line-color": "#000000",
        "curve-style": "bezier",
        "target-arrow-shape": "triangle",
        "arrow-scale": 2
      }
    },
    {
      selector: "edge#UK2DE",
      style: {
        label: "data(label)",
        "source-label": "data(source)",
        "target-label": "data(target)",
        "source-text-offset": 20,
        "target-text-offset": 25,
        "text-rotation": "autorotate",
        width: 3,
        "line-color": "#c0c",
        "target-arrow-color": "#00c",
        "curve-style": "bezier",
        "target-arrow-shape": "triangle",
        "arrow-scale": 2
      }
    },
    {
      selector: ".highlight",
      css: {
        "background-color": "yellow"
      }
    }
  ],
  layout: {
    name: "preset"
  }
})

cy.on('click', 'edge', function(e) {
  //console.log(this.source().id(), this.target().id());
  const src = this.source().id();
  const tgt = this.target().id();
  console.log(`Src: ${src}, Target: ${tgt}`);
  console.log("Src(x,y):" + cy.$("#" + src).position());
  //output "Src(x,y):[object Object]"
  // Question: How to get (x,y) without using JSON.parse(JSON.stringify(..)) at this step

  //const srcxy = JSON.parse(JSON.stringify( cy.$("#"+src).position() ));
  //const tgtxy = JSON.parse(JSON.stringify( cy.$("#"+tgt).position() ));
  //console.log("Src(x,y): " + srcxy.x + ", " + srcxy.y);
  //console.log("Tgt(x,y): " + tgtxy.x + ", " + tgtxy.y);
});
#cy {
  width: 60%;
  height: 70%;
  position: absolute;
  top: 4px;
  left: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.29.2/cytoscape.min.js"></script>
<div id="cy"></div>

My question is: when I click the edge, I get the output as output "Src(x,y):[object Object]", how to avoid using JSON.parse(JSON.stringify(..)) to get the positions (x,y) of the nodes.


Solution

  • This isn't really a cytoscape.js question.

    There are a couple ways you can do this. One is to decompose the position object and print the x,y like this.

    const pos = cy.$("#" + src).position();
    const { x1, y1 } = pos; // I think its x1, y1 and not x, y
    console.log(`Src(${x1},${y1})`);
    

    Here's a trick I use when I'm just debugging code. The console.log() function actually takes multiple parameters. If you use pass the position object as a second parameter it will appear as an object you can interact with in the Chrome debugger.

    console.log("Src(x,y):", cy.$("#" + src).position());