Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

254
Visualizações
D3.js - create new node in visible area when zoomed

I am currently working on a force-directed d3 graph utilizing the zoom function. The user has the option to create new nodes on the graph. This is utilized via a double click event on the graph to get the coordinates at which the new node is created.

It is possible, and during the user's daily work quite common, that the double clicks on the graph, then zooms to another area and/or changes the scaling, and then finished the creation of the node (setting attributes). In this case, the node is suppose to be created in the visible area of the graph.

For this scenario, I wrote a function that takes the to be created node and the svg element and mutated the node's coordinates to center it in the visible area, if necessary:

  moveNodeIntoViewPort(node: NodeInterface, svgElement: any): NodeInterface {
    let svg = svgElement._groups[0][0];
    let minX: number = parseInt(svg.attributes.viewBox.nodeValue.split(" ")[0]);
    let minY: number = parseInt(svg.attributes.viewBox.nodeValue.split(" ")[1]);
    let width: number = parseInt(
      svg.attributes.viewBox.nodeValue.split("  ")[1].split(" ")[0]
    );
    let height: number = parseInt(
      svg.attributes.viewBox.nodeValue.split("  ")[1].split(" ")[1]
    );
    let zoomX: number = parseInt(svg.__zoom.x) * -1;
    let zoomY: number = parseInt(svg.__zoom.y) * -1;
    let zoomK: number = parseFloat(svg.__zoom.k.toFixed(2));

    node.x =
      node.x < minX + zoomX || node.x > minX + width + zoomX
        ? (minX + zoomX + width / 2) / zoomK
        : node.x;

    node.y =
      node.y < minY + zoomY || node.y > minY + height + zoomY
        ? (minY + zoomY + height / 2) / zoomK
        : node.y;

    return node;
  }

Although this code works as intended, I am not satisfied with the code itself and am wondering, if D3 offers any better solution out of the box. I could not find any information in the official D3 documentation about how to:

  • check, if a node is visible in the zoomed area
  • how to get the current center coordinates of a zoomed graph

Any input is greatly appreciated.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

After some research (and with some help), we managed to realize the same result with following code using a DOMMatrix:

  moveNodeIntoViewPort(node: NodeInterface, svgElement: any): NodeInterface {
    let transformationMatrix = this.viewportRef._groups[0][0].getScreenCTM();

    const nodePoint = new DOMPoint(node.x, node.y).matrixTransform(
      transformationMatrix
    );

    let currentViewport = svgElement._groups[0][0].getBoundingClientRect();
    let centerPoint = new DOMPoint(
      currentViewport.left + currentViewport.width / 2,
      currentViewport.top + currentViewport.height / 2
    ).matrixTransform(transformationMatrix.inverse());

    if (
      nodePoint.x < currentViewport.left ||
      nodePoint.x > currentViewport.right ||
      nodePoint.y < currentViewport.top ||
      nodePoint.y > currentViewport.bottom
    ) {
      node.x = centerPoint.x;
      node.y = centerPoint.y;
    }

    return node;
  }

viewportRef is the d3 selection of the <g class="viewport> child of the <svg> element.

Although not quite shorter than the original function, as it is now, we can prevent using string manipulation and may extract part of the function to be used in other processes.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda