【问题标题】:Segemented SVG Outlined Circle分段的 SVG 轮廓圆
【发布时间】:2022-12-04 22:09:07
【问题描述】:

在此先感谢您的帮助!

我正在尝试构建一个 SVG 圆圈,它没有填充只有一个轮廓并且被分成 3 个部分。

我设法找到了一个线程,告诉我如何将一个圆分成 4 段(见 sn-p),但我对 SVG 很陌生,所以我真的不知道发生了什么以及如何将它分成 3 段而且只有大纲。

我附上了显示圆圈结果的屏幕截图。我不想要段的任何可见标志,但我希望能够单独使用每个段。 (基本上,当您向下滚动页面时,我将拥有一个圆圈自行完成的页面。)

        <svg width="200" height="200" viewBox="0 0 200 200">
          <g transform="translate(100,100)" stroke="#000" stroke-width="2">
            <path d="M0 0-70 70A99 99 0 0 1-70-70Z" fill="none"/>
            <path d="M0 0-70-70A99 99 0 0 1 70-70Z" fill="none"/>
            <path d="M0 0 70-70A99 99 0 0 1 70 70Z" fill="none"/>
            <path d="M0 0 70 70A99 99 0 0 1-70 70Z" fill="none"/>
          </g>
        </svg>

【问题讨论】:

  • 这取决于你所说的“大纲”是什么意思。我怀疑您的意思是要将圆弧绘制为粗线。 SVG 称之为“笔画”。那正确吗?另一种方法是段形状是轮廓并用颜色填充的地方。换句话说,两条不同半径的圆弧在其末端由直线连接。然后填充蓝色/绿色。
  • 如果您想了解路径的工作原理。您可以在Paths section of the SVG specification 中阅读有关它们的信息。没那么复杂。

标签: html css svg geometry


【解决方案1】:

代替所有数学,让原生 Web 组件 &lt;svg-segments&gt; 完成工作。
中的重要部分创建SVG &lt;path&gt;pathLengthstroke-dasharray

全部你指定,是一个细绳定义绘制多少和什么颜色段的颜色。
无颜色将创建一个空段:

&lt;svg-segments parts="red,,blue"&gt;&lt;/svg-segments&gt;

在下面的 SO sn-p 中;单击圆圈以添加更多细分

<div style="display:grid;grid:1fr/repeat(5,1fr);gap:10px;background:grey">
  <svg-segments parts="red,green,blue"></svg-segments>
  <svg-segments parts="red,,blue"></svg-segments>
  <svg-segments parts=",,red"></svg-segments>
  <svg-segments parts="red,green,blue,purple" width="5"></svg-segments>
  <svg-segments parts="red,,,green,,blue,,red,red" width="50"></svg-segments>
</div>
<script>
  customElements.define("svg-segments", class extends HTMLElement {
    static get observedAttributes() {
      return ["parts", "size"]; // svg is redrawn at *every* attribute update!
    }
    attributeChangedCallback() {
      this.parts = this.getAttribute("parts").split(",");
      let vb = 200; // viewPort size; might need to tweak this
      let width = this.getAttribute("width") || 25; // stroke-width
      let a = vb / 2 - width/2; // calculate circle arcs
      let b = vb - width;
      this.innerHTML = `<svg viewBox='0 0 ${vb} ${vb}'>` +
        this.parts.map((col, idx) => {
          if (col)
            return `<path d='M${width/2},${vb/2}a${a},${a} 0 1,0 ${b},0a${a},${a} 0 1,0 -${b},0' 
            fill='none' stroke-width='${width}' pathLength='${this.parts.length}'
            stroke='${col}' stroke-dashoffset='${idx}'
            stroke-dasharray='1 ${this.parts.length-1}'/>`;
          else return ``;
        }) + `</svg>`;
    }
    connectedCallback() {// for StackOverflow Snippet demo purpose only
      this.onclick = (evt) => { 
        let moreparts = this.parts.join(",") + ",red";
        this.setAttribute("parts", moreparts);
      }
    }
  })
</script>

SVG 在计算路径弧时有一些怪癖,当您看到工件(红色)时,您可能需要将视口尺寸调整到更高的尺寸:

或者重构使用&lt;circle&gt;

【讨论】:

    【解决方案2】:

    您将需要计算每条弧的起点和终点。因为你想要 3 条弧,所以使用的角度是圆的 1/3,即 2*Math.PI/3。

    请阅读代码中的cmets。

    //the circle's radius
    let r = 70;
    //points used for the start and end of every arc
    let points =[];
    //the paths
    let ps = document.querySelectorAll("path");
    
    //calculating the points used for the start and end of every arc
    for(let angle = -Math.PI/2; angle < 2*Math.PI; angle += 2*Math.PI/3 ){
      let point = {}
      point.x = r * Math.cos(angle);
      point.y = r * Math.sin(angle);
      points.push(point)
    }
    
    //defining the valueof the d attribute of every path as an arc with the given radius, starting at the previous point and ending at the actual point
    for(let i = 0,l=points.length; i<l-1; i++){
      let point = points[i+1];
      let prev = points[i]
      let d = `M${prev.x},${prev.y} A${r},${r},0,0,1,${point.x},${point.y}`
      //setting the d attribute
      ps[i].setAttribute("d",d);
    }
    svg{border:solid}
    <svg viewBox="-100 -100 200 200" width="300" fill="none" stroke-width="20">
      <path stroke="gold"/>
      <path stroke="skyBlue"/>
      <path stroke="tomato"/>
    </svg>

    【讨论】:

      猜你喜欢
      • 2020-05-22
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 2012-09-26
      • 2020-01-30
      • 2019-01-26
      相关资源
      最近更新 更多