skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    The answer is simple, just access the coordinate components x and y direcly. To get x and y coordinates of the source node, use

    cy.$(`#${src}`).position().x
    cy.$(`#${src}`).position().y
    

    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}`);
      
      // This is the problem, coordinates are not shown:
      console.log("Src(x,y):" + cy.$(`#${src}`).position());
      //output "Src(x,y):[object Object]"
      
      // These are the solution:
      console.log("Src(x,y): " + cy.$(`#${src}`).position().x + ", " + cy.$(`#${src}`).position().y);
      //output "Src(x,y): 100, 100"
      console.log("Src(x,y):", cy.$(`#${src}`).position());
      //output: Src(x,y): {"x": 100,"y": 100}
      console.log("Src(x,y): "+ cy.$(`#${src}`).position().x +", " + cy.$(`#${src}`).position().y);
      //output: Src(x,y): 100, 100
    });
    #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>


  2. 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());
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search