SVG绘制一个包含4个扇区的圆圈

时间:2015-09-23 22:36:18

标签: html svg trigonometry

我需要画一个有4个扇区的圆圈。我正在尝试绘制这样一个扇区:

<path d="M200, 200, l 100,-100 a180,180 0 0,0 -127.27,127.27 z"/>

我从等式得到-127.27,127.27:

x=cos(angle) * radius
y=sin(angle) * radius

我的角度是135,我的半径是180。

这是我得到的代码:http://codepen.io/anon/pen/QjKgdY蓝色的是我在这里谈论的那个,黑色的是我尝试不同的数字。

为什么我没有得到合适的1/4圈?我错过了什么?

4 个答案:

答案 0 :(得分:17)

这些数字没有多大意义。首先移动到(200,200),然后画一条直线到(300,100)(长度:141个单位),然后是一个以(172.73,227.27)结尾的圆弧(半径180个单位)。不应该直线段的长度至少等于圆的半径?

你让自己的生活变得非常困难。如果要绘制四个圆形线段,最好的第一步是使用<g>元素将坐标系移动到圆的中心。然后,您可以使用几乎相同的代码创建所有四个段。

以下是一个例子:

&#13;
&#13;
<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="#f00"/>
    <path d="M0 0-70-70A99 99 0 0 1 70-70Z" fill="#080"/>
    <path d="M0 0 70-70A99 99 0 0 1 70 70Z" fill="#dd0"/>
    <path d="M0 0 70 70A99 99 0 0 1-70 70Z" fill="#04e"/>
  </g>
</svg>
&#13;
&#13;
&#13;

如果您想要一个半径不同的圆圈,请将99替换为您想要的半径,并将70替换为此值乘以sqrt(0.5)。

路径数据细分:

M0 0-70 70

Move(0,0),然后画一条直线到(-70,70)(隐含L)。

A99 99 0 0 1-70-70

使用(-70,-70)rx=rx=99x-axis-rotation=0large-arc-flag=1sweep-flag=0Z 。 (最后两个参数描述为elliptical arc)。

a

here路径。

答案 1 :(得分:4)

我真的很懒,所以当我需要绘制弧线时,我会使用以下脚本: 我创建了一个单位向量:

stop
然后我为我的轮换设置了一个矩阵:

var p = svgElem.createSVGPoint()
p.x = 0
p.y = 1

最后我旋转单位矢量并将其平移/缩放到我想要的位置。

var m = svgElem.createSVGMatrix()

现在如果我想对片段进行硬编码,我可以var p2 = p.matrixTransform(m.rotate(45)) p2.x = cx + p2.x*rx p2.y = cy + p2.y*ry ,或者你可以从脚本创建片段。

这里有一个基本的例子(我知道,对于像上面这样的简单案例,这不是必需的,但它是一个简单的通用解决方案,在过去几年中帮助了我很多......)

console.log(p2.x,p2.y)
var svgElem=document.getElementById("svg");
var cx=100;
var cy=100;
var rx=90;
var ry=90;

var p = svgElem.createSVGPoint();
    p.x = 0;
    p.y = 1;


var m = svgElem.createSVGMatrix();


var p2 = p.matrixTransform(m.rotate(45));
    p2.x = cx + p2.x*rx;
    p2.y = cy + p2.y*ry;
    
    console.log(p2.x,p2.y);

var path = document.createElementNS("http://www.w3.org/2000/svg","path");
    svgElem.appendChild(path);
var d="M"+cx+" "+(cy+ry)+"A"+rx+" "+ry+" 0 0 1"+p2.x+" "+p2.y+"L"+cx+" "+cy+"z";
    path.setAttribute("d",d)

答案 2 :(得分:4)

以下是我在SVG组件中使用React扇区路径进行编程生成的函数:

getSectorPath(x, y, outerDiameter, a1, a2) {
    const degtorad = Math.PI / 180;
    const halfOuterDiameter = outerDiameter / 2;
    const cr = halfOuterDiameter - 5;
    const cx1 = (Math.cos(degtorad * a2) * cr) + x;
    const cy1 = (-Math.sin(degtorad * a2) * cr) + y;
    const cx2 = (Math.cos(degtorad * a1) * cr) + x;
    const cy2 = (-Math.sin(degtorad * a1) * cr) + y;

    return "M" + x + " " + y + " " + cx1 + " " + cy1 + " A" + cr + " " + cr + " 0 0 1 " + cx2 + " " + cy2 + "Z";
}

以下是用法:

<svg width={outerDiameter} height={outerDiameter}>
    <path d={this.getSectorPath(outerDiameter / 2, outerDiameter / 2, outerDiameter, 45, 135)} fill="#f00"/>
    <path d={this.getSectorPath(outerDiameter / 2, outerDiameter / 2, outerDiameter, 135, 225)} fill="#f00"/>
    <path d={this.getSectorPath(outerDiameter / 2, outerDiameter / 2, outerDiameter, 225, 315)} fill="#f00"/>
    <path d={this.getSectorPath(outerDiameter / 2, outerDiameter / 2, outerDiameter, 315, 45)} fill="#f00"/>
</svg>

答案 3 :(得分:0)

这是我从JavaScript创建svg的示例。我写它的灵感来自@zmechanic答案。一个扇区具有梯度。 要执行它,只需创建一个html文档并复制内容。

<!DOCTYPE html>
<html>
  <body>
    <div id="svgRoot"></div>
    <script type="text/javascript">
      const DIAMETER = 200;
      const SVG_SIZE = DIAMETER + 12;
      const STROKE = "black";
      const STROKE_WIDTH = "2";

      const getSectorPath = (x, y, outerDiameter, a1, a2) => {
        const degtorad = Math.PI / 180;
        const cr = outerDiameter / 2;
        const cx1 = Math.cos(degtorad * a2) * cr + x;
        const cy1 = -Math.sin(degtorad * a2) * cr + y;
        const cx2 = Math.cos(degtorad * a1) * cr + x;
        const cy2 = -Math.sin(degtorad * a1) * cr + y;

        return `M${x} ${y} ${cx1} ${cy1} A${cr} ${cr} 0 0 1 ${cx2} ${cy2}Z`;
      };

      const svgRoot = document.getElementById("svgRoot");
      const pieChartSvgString = `<svg width="${SVG_SIZE}" height="${SVG_SIZE}">
        <defs>
          <linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" style="stop-color:#DD5E89;stop-opacity:1" />
            <stop offset="100%" style="stop-color:#F7BB97;stop-opacity:1" />
          </linearGradient>
        </defs>
        <g fill="url(#gradient1)">
          <path
            stroke="${STROKE}"
            strokeWidth="${STROKE_WIDTH}"
            d="${getSectorPath(SVG_SIZE / 2, SVG_SIZE / 2 - 5, DIAMETER, 45, 135)}"
          />
        </g>
        <path
          stroke="${STROKE}"
          strokeWidth="${STROKE_WIDTH}"
          d="${getSectorPath(SVG_SIZE / 2, SVG_SIZE / 2, DIAMETER, 135, 225)}"
          fill="#00ff00"
        />
        <path
          stroke="${STROKE}"
          strokeWidth="${STROKE_WIDTH}"
          d="${getSectorPath(SVG_SIZE / 2, SVG_SIZE / 2, DIAMETER, 225, 315)}"
          fill="#0000ff"
        />
        <path
          stroke="${STROKE}"
          strokeWidth="${STROKE_WIDTH}"
          d="${getSectorPath(SVG_SIZE / 2, SVG_SIZE / 2, DIAMETER, 315, 45)}"
          fill="#ffff00"
        />
      </svg>`;
      const svgNode = document.createRange().createContextualFragment(pieChartSvgString);
      svgRoot.appendChild(svgNode);
    </script>
  </body>
</html>

相关问题