【问题标题】:D3.js replace points in svg pathD3.js 替换 svg 路径中​​的点
【发布时间】:2021-02-08 18:30:03
【问题描述】:

我已经预渲染了弯曲的 svg 路径,点看起来像这样

d="M 547, 699 C 547, 759 347, 236, 347, 296"

我需要的是一种使所有这些线笔直的方法,基本上直接连接第一个点和最后一个点,就像那样

d="M 547, 699, 347, 296"

我正在使用 D3 来修改 svg 元素。我尝试使用 attr("d") 读取当前 d 属性,然后使用正则表达式将其更改为第二种格式并使用 attr("d", newPath) 将其设置回节点,但它不起作用。我该怎么做?

编辑: 我尝试替换路径点的代码是这样的:

var d = d3.select(".nodes-path").attr("d");
d = d.replace(/\D/g, ",");
var dArray = d.split(",");
var newPath = "M " +
      dArray[0] +
      ", " +
      dArray[1] +
      ", " + //now I know it should be ", L " on this line
      dArray[dArray.length - 2] +
      ", " +
      dArray[dArray.length - 1];
d3.select(".nodes-path").attr("d", newPath);

路径看起来像这样:

<path d="M 547, 502 C 547, 562 347, 236, 347, 296" class="nodes-path"></path>

但它不会改变路径中的 d 属性。我还需要一种方法来使其循环(现在选择有效,因为我只有一个路径,但还会有更多),可能使用 selectAll,但不知道如何获取属性,然后通过调整将其设置回来.

edit2:但如果我这样做:

d3.select(".canvas-layer")
      .append("g")
      .append("path")
      .attr("d", "M 547, 502 L 347, 296")
      .attr("class", "nodes-path");

它显示了两条路径,一条弯曲,一条笔直。所以问题是读取并设置渲染路径的属性d。怎么做?

【问题讨论】:

  • 您需要使用 jQuery/querySelector/CSS 语法来选择您的路径:d3.select(".nodes-path")。注意前面的点
  • 不幸的是,jQuery 不是一个选项 :(
  • 我的意思是风格是一样的,不是说你应该用jQuery。只需在选择器前面加一个句号
  • 呃,我明白了,事情是,我有这个点,不知道为什么我复制时它消失了,一定是我调整了一些东西以使其更具可读性时不小心删除了它。但是还是不行
  • 这两个地方都需要加上,还有d3.select(".nodes-path").attr("d", newPath);

标签: javascript svg d3.js


【解决方案1】:

当我将您的代码放入 sn-p 时,它会立即更新,但新路径不是有效路径。

var d = d3.select(".nodes-path").attr("d");
d = d.replace(/\D/g, ",");
var dArray = d.split(",");
var newPath = "M " +
  dArray[0] +
  ", " +
  dArray[1] +
  ", " + //now I know it should be ", L " on this line
  dArray[dArray.length - 2] +
  ", " +
  dArray[dArray.length - 1];
d3.select(".nodes-path").attr("d", newPath);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg viewbox="200 200 600 600">
  <path d="M 547, 699 C 547, 759 347, 236, 347, 296" class="nodes-path"></path>
</svg>

原因是您用逗号替换了 除了数字之外的所有内容,但随后的逗号也会重复。我可以使用正则表达式将路径拆分为 MoveTo 部分和 Bezier 曲线,然后像这样附加最后的部分:

var d = d3.select(".nodes-path").attr("d");
// First, just get the start of the path in one piece
var start = d.substr(0, d.indexOf("C"));
var dArray = d.split(",");
var newPath = start +
  "L" +
  dArray[dArray.length - 2] +
  ", " +
  dArray[dArray.length - 1];
d3.select(".nodes-path").attr("d", newPath);
path {
  stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg viewbox="200 200 600 600">
  <path d="M 547, 699 C 547, 759 347, 236, 347, 296" class="nodes-path"></path>
</svg>

【讨论】:

  • 你是对的。但由于某种原因,我无法达到相同的结果。我从 attr("d") 什么也没得到。我在 react useEffect 钩子中使用此代码,但这没关系,因为我可以轻松访问此节点的其他属性,例如类,它们可以很好地显示在控制台中。此外,即使我硬编码新路径, attr("d", newPath) 也不会更新它
  • 这可能是一个时间问题,d 尚未设置?那么useEffect 在你的渲染函数之前被调用了吗?
  • 是的,svg 目前还没有完成绘制,我一直在尝试更新路径。设置超时就可以了,并且使用了您的代码,并且它起作用了。如果只有一种方法可以将事件侦听器添加到 svg,那么它会在 svg 完成绘制的那一刻更新。但这是不同的问题,感谢您的帮助! :)
猜你喜欢
  • 2015-02-13
  • 1970-01-01
  • 2021-04-10
  • 2022-01-26
  • 2012-08-17
  • 2014-05-02
  • 2017-11-26
  • 1970-01-01
相关资源
最近更新 更多