【问题标题】:SVG: how to draw multiple semicircles (arcs) pathSVG:如何绘制多个半圆(弧)路径
【发布时间】:2021-10-16 16:54:36
【问题描述】:

使用this thread 的答案,我能够画出一个半圆(弧线):

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;

  return {
    x: centerX + (radius * Math.cos(angleInRadians)),
    y: centerY + (radius * Math.sin(angleInRadians))
  };
}

function describeArc(x, y, radius, startAngle, endAngle) {

  var start = polarToCartesian(x, y, radius, endAngle);
  var end = polarToCartesian(x, y, radius, startAngle);

  var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

  var d = [
    "M", start.x, start.y,
    "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
  ].join(" ");
  console.log(d)
  return d;
}

window.onload = function() {
  document.getElementById("arc1").setAttribute("d", describeArc(100, 100, 50, -90, 90));
};
<svg width="1000" height="1000">
  <path id="arc1" fill="red" stroke="#446688" stroke-width="2" />
</svg>

我想要实现的是能够将 SVG 绘制为与许多弧(半圆)一致的路径,并能够在它们上设置 fill

类似这样的:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M 50 100 A 10 10 0 0 1 100 100 M 100 100 A 10 10 0 0 1 150 100 M 150 100 A 10 10 0 0 1 200 100 M 200 100 A 10 10 0 0 1 250 100" fill="red" stroke="blue" stroke-width="3" />
</svg>

有没有更好的方法来实现更简单的路径?现在,它看起来像这样:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M 50 100 A 10 10 0 0 1 100 100 M 100 100 A 10 10 0 0 1 150 100 M 150 100 A 10 10 0 0 1 200 100 M 200 100 A 10 10 0 0 1 250 100" fill="red" stroke="blue" stroke-width="3" />
</svg>

或者当有 30 个半圆时,我是否必须生成越来越长的路径?

编辑:需要 IE9+ 支持。此外,这些元素将是可点击、可拖动和可控的。可控是指鼠标点击/移动时它们的数量和大小会发生变化。

我选择我的第一种方法是动态的很长的路径。

谢谢!

【问题讨论】:

标签: javascript svg drawing


【解决方案1】:

为此,我将使用小写命令。例如,这是绘制您需要的圆弧:半径为 25 的圆弧,终点距圆弧起点 50 个单位 ( 2 * 25 )。

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M 50 100 a 25 25 0 0 1 50 0" fill="red" stroke="blue" stroke-width="3" />
</svg>

为了获得 4 条弧线的路径,您需要将弧线 (a 25 25 0 0 1 50 0) 重复 4 次,如下所示:

<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M 50 100 a 25 25 0 0 1 50 0 
                    a 25 25 0 0 1 50 0 
                    a 25 25 0 0 1 50 0 
                    a 25 25 0 0 1 50 0 " fill="red" stroke="blue" stroke-width="3" />
</svg>

很容易看出如何使用 javascript 生成所需的 d 属性:

let d ="M 50 100";

for(let i=0; i<4;i++){d +="a 25 25 0 0 1 50 0 "}

document.querySelector("path").setAttribute("d",d);
<svg xmlns="http://www.w3.org/2000/svg">
  <path d="M 50 100" fill="red" stroke="blue" stroke-width="3" />
</svg>

【讨论】:

  • 谢谢!我大概会走这条路!我会在星期一进行更深入的调查:)
  • 而不是那个for循环:d="M50 100 "+"a 25 25 0 0 1 50 0 ".repeat(4) ...哦..该死的.. OP想要IE11支持...嗯..它适用于现代浏览器..
【解决方案2】:

您可以使用 vanilla JavaScript Web 组件(所有现代浏览器都支持)创建 SVG

您的自定义元素 &lt;svg-arcs repeat="7"&gt;&lt;/svg-arcs&gt; 然后创建:

<style>
  svg { background: pink }
  svg path { stroke-width: 3 }
</style>

<svg-arcs repeat="30"></svg-arcs>

<script>
  customElements.define("svg-arcs", class extends HTMLElement {
    connectedCallback() {
      let repeat = this.getAttribute("repeat") || 5;
      let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      for (let x = 0; x < repeat; x++) {
        let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
        path.setAttribute("d", `M${3 + 50*x} 100 A 10 10 0 0 1 ${50+50*x} 100`);
        path.setAttribute("fill", "red");
        path.setAttribute("stroke", "blue");
        svg.append(path);
      }
      svg.setAttribute("viewBox", `0 0 ${50*repeat + 3} 150`);
      this.append(svg);
    }
  })
</script>

有关对单个弧的更多动态控制,请参阅 SO 帖子中的 Web 组件Firefox: shadow-DOM compatibility

【讨论】:

  • 谢谢!但我宁愿只坚持一条路。此外,我不确定是否可以在必须支持所有旧浏览器的 TypeScript 项目中使用它。无论如何,好主意!
  • 在您的下一个 SO 帖子中,提及您需要 IE11 支持。 tnx
  • 对不起。这是我在过去 3 年中关于 SO 的第一个问题,也许是第二个问题。下次我会记住的
【解决方案3】:

您可以使用图案并适当调整图案对象的大小。这是一个可容纳 4 次迭代的版本。

编辑和更新: 如果您希望这些弧线可以独立点击/拖动,那么它们需要在 DOM 中单独寻址。 “使用”元素可能就是您要寻找的。​​p>

    svg {
    background: grey;
    }
    <svg width="800px" height="600px">
      <defs>
       <path id="arc-template" d="M1.5 50 a 10 10 0 0 1 97 0" fill="red" stroke="blue" stroke-width="3" />
      </defs>
      
     <use id="arc1" href="#arc-template" x="50" y="100"/>
     <use id="arc2" href="#arc-template" x="150" y="100"/>
     <use id="arc3" href="#arc-template" x="250" y="100"/>
     <use id="arc4" href="#arc-template" x="350" y="100"/>
         
    </svg>

【讨论】:

  • 感谢你 :) 但这些元素必须是可点击和可拖动的。使用模式时,有一个矩形,不应该在半圆之间单击。
  • 元素不必分开。它们可以被视为一个元素。但是您使用“使用”的第二个解决方案非常好,我会在星期一考虑。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 2012-12-24
  • 2012-07-08
  • 2014-12-28
  • 1970-01-01
  • 1970-01-01
  • 2013-11-23
相关资源
最近更新 更多