D3.js -缩放时在可见区域中创建新节点

yruzcnhs  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(197)

我目前正在使用zoom函数制作一个强制d3图。用户可以选择在图上创建新节点。这是通过双击图上的事件来获得创建新节点的坐标。
在用户的日常工作中,双击图形,然后缩放到另一个区域和/或更改缩放比例,然后完成节点的创建(设置属性),这是可能的,也是很常见的。在这种情况下,节点应该在图形的可见区域中创建。
对于这个场景,我编写了一个函数,它接受要创建的节点和svg元素,并在必要时改变节点的坐标,使其位于可见区域的中心:

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;
  }

虽然这段代码能按预期工作,但我对代码本身并不满意,我想知道D3是否提供了更好的现成解决方案。我在official D3 documentation中找不到任何关于如何:

  • 如果节点在缩放区域中可见,请检查
  • 如何获取缩放图形的当前中心坐标

我们非常感谢您的任何意见。

h7appiyu

h7appiyu1#

经过一些研究(并在一些帮助下),我们使用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<svg>元素的<g class="viewport>子元素的d3选择。
虽然没有比原来的函数更短,但是我们可以避免使用字符串操作,并且可以提取部分函数用于其他进程。

相关问题