Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何计算圆弧(圆)的SVG路径_Svg - Fatal编程技术网

如何计算圆弧(圆)的SVG路径

如何计算圆弧(圆)的SVG路径,svg,Svg,给定一个以(200200)为圆心,半径为25的圆,如何从270度到135度以及从270度到45度绘制圆弧 0度表示它正好位于x轴(右侧)(表示它是3点钟位置) 270度表示它是12点钟位置,90度表示它是6点钟位置 更一般地说,圆弧的路径是什么 x, y, r, d1, d2, direction 意义 center (x,y), radius r, degree_start, degree_end, direction 你想用这个。不幸的是,这需要指定起点和终点的笛卡尔坐标(x,y),而不

给定一个以(200200)为圆心,半径为25的圆,如何从270度到135度以及从270度到45度绘制圆弧

0度表示它正好位于x轴(右侧)(表示它是3点钟位置) 270度表示它是12点钟位置,90度表示它是6点钟位置

更一般地说,圆弧的路径是什么

x, y, r, d1, d2, direction
意义

center (x,y), radius r, degree_start, degree_end, direction
你想用这个。不幸的是,这需要指定起点和终点的笛卡尔坐标(x,y),而不是现有的极坐标(半径、角度),因此必须进行一些数学计算。下面是一个JavaScript函数,它应该可以工作(尽管我还没有测试过),我希望它是不言自明的:

function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
  var angleInRadians = angleInDegrees * Math.PI / 180.0;
  var x = centerX + radius * Math.cos(angleInRadians);
  var y = centerY + radius * Math.sin(angleInRadians);
  return [x,y];
}
哪个角度对应于哪个时钟位置取决于坐标系;只要根据需要交换和/或否定sin/cos术语即可

arc命令具有以下参数:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y
第一个例子是:

rx
=
ry
=25和
x轴旋转
=0,因为您想要的是圆而不是椭圆。您可以使用上述函数计算起始坐标(应
M
ove to)和结束坐标(x,y),分别得到(200,175)和(182.322,217.678)左右。考虑到目前为止的这些约束,实际上可以绘制四条圆弧,因此两个标志选择其中一条。我猜你可能想画一个小弧线(意思是
大弧线标志
=0),沿角度减小的方向(意思是
扫掠标志
=0)。总之,SVG路径是:

M 200 175 A 25 25 0 0 0 182.322 217.678
M 200 175 A 25 25 0 1 0 217.678 217.678
对于第二个示例(假设您的意思是朝同一方向走,因此是一个大圆弧),SVG路径是:

M 200 175 A 25 25 0 0 0 182.322 217.678
M 200 175 A 25 25 0 1 0 217.678 217.678
再说一次,我还没有测试过这些

(编辑2016-06-01)如果像@clocksmith一样,你想知道他们为什么选择这个API,请看一下。他们描述了两种可能的圆弧参数化,“端点参数化”(他们选择的那个)和“中心参数化”(这与问题所使用的类似)。在“端点参数化”的描述中,他们说:

端点参数化的优点之一是它允许一致的路径语法,其中所有路径命令都以新“当前点”的坐标结束

因此,基本上,这是一个副作用的弧被视为一个更大的路径,而不是他们自己的单独对象的一部分。我认为,如果SVG渲染器不完整,它可以跳过它不知道如何渲染的任何路径组件,只要它知道它们使用了多少参数。或者,它可以使用许多组件对路径的不同块进行并行渲染。或者他们这样做是为了确保舍入误差不会沿着复杂路径的长度累积


实现说明对于原始问题也很有用,因为它们有更多的数学伪代码用于在两个参数化之间转换(我第一次写这个答案时没有意识到这一点)。

扩展@wdebeaum的伟大答案,下面是一个生成弧形路径的方法:

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(" ");

    return d;       
}
在你的html中

<path id="arc1" fill="none" stroke="#446688" stroke-width="20" />

我对圆形部分进行了轻微修改并制作了支撑填充。

JS

函数极坐标(centerX、centerY、半径、角度等){
var angleInRadians=(angleInDegrees-90)*Math.PI/180.0;
返回{
x:centerX+(半径*数学坐标(角半径)),
y:中心y+(半径*数学正弦(角度半径))
};
}
函数描述C(x,y,半径,星形,端角){
var起点=极笛卡尔坐标(x,y,半径,端角);
var end=极笛卡尔坐标(x,y,半径,星形);

var arcSweep=endAngle-startAnglewdebeaum的原始极笛卡尔函数是正确的:

var angleInRadians = angleInDegrees * Math.PI / 180.0;
使用以下方法反转起点和终点:

var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
(对我来说)令人困惑,因为这将反转扫描标志。使用:

var start = polarToCartesian(x, y, radius, startAngle);
var end = polarToCartesian(x, y, radius, endAngle);
使用sweep flag=“0”绘制“正常”计数器时钟方向的圆弧, 我认为这更直截了当。
参见

我想对@Ahtenus answer发表评论,特别是对Ray Hulha的评论,他说代码笔没有显示任何弧度,但我的声誉不够高

这个代码笔不工作的原因是它的html错误,笔划宽度为零

我修复了它,并在这里添加了第二个示例:

html:

<svg>
    <path id="theSvgArc"/>
    <path id="theSvgArc2"/>
</svg>
javascript:

document.getElementById("theSvgArc").setAttribute("d", describeArc(150, 150, 100, 0, 180));
document.getElementById("theSvgArc2").setAttribute("d", describeArc(300, 150, 100, 45, 190));

对@opsb的答案稍作修改。我们不能用这种方法画一个完整的圆圈。即,如果我们给出(0,360),它将不会画任何东西。因此,稍作修改即可解决此问题。显示有时达到100%的分数可能很有用

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 endAngleOriginal = endAngle;
    if(endAngleOriginal - startAngle === 360){
        endAngle = 359;
    }

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

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

    if(endAngleOriginal - startAngle === 360){
        var d = [
              "M", start.x, start.y, 
              "A", radius, radius, 0, arcSweep, 0, end.x, end.y, "z"
        ].join(" ");
    }
    else{
      var d = [
          "M", start.x, start.y, 
          "A", radius, radius, 0, arcSweep, 0, end.x, end.y
      ].join(" ");
    }

    return d;       
}

document.getElementById("arc1").setAttribute("d", describeArc(120, 120, 100, 0, 359));
函数极坐标(centerX、centerY、半径、角度等){
var angleInRadians=(angleInDegrees-90)*Math.PI/180.0;
返回{
x:centerX+(半径*数学坐标(角半径)),
y:中心y+(半径*数学正弦(角度半径))
};
}
函数描述C(x,y,半径,星形,端角){
var endAngleOriginal=endAngle;
if(endAngleOriginal-startAngle==360){
端角=359;
}
var起点=极笛卡尔坐标(x,y,半径,端角);
var end=极笛卡尔坐标(x,y,半径,星形);

var arcSweep=endAngle-startAngle@opsb的答案很简洁,但中心点并不准确,而且,正如@Jithin所指出的,如果角度是360度,则根本不会绘制任何图形

@Jithin修复了360度的问题,但是如果选择小于360度,则会得到一条闭合圆弧环的线,这不是必需的

我修复了这个问题,并在下面的代码中添加了一些动画:

函数myArc(cx,cy,半径,max){
var circle=document.getElementById(“弧”);
var e=circle.getAttribute(“d”);
var d=“M”+(cx+半径)+++cy;
var角=0;
window.timer=window.setInterval(
函数(){
var弧度=ang
document.getElementById("theSvgArc").setAttribute("d", describeArc(150, 150, 100, 0, 180));
document.getElementById("theSvgArc2").setAttribute("d", describeArc(300, 150, 100, 45, 190));
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 endAngleOriginal = endAngle;
    if(endAngleOriginal - startAngle === 360){
        endAngle = 359;
    }

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

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

    if(endAngleOriginal - startAngle === 360){
        var d = [
              "M", start.x, start.y, 
              "A", radius, radius, 0, arcSweep, 0, end.x, end.y, "z"
        ].join(" ");
    }
    else{
      var d = [
          "M", start.x, start.y, 
          "A", radius, radius, 0, arcSweep, 0, end.x, end.y
      ].join(" ");
    }

    return d;       
}

document.getElementById("arc1").setAttribute("d", describeArc(120, 120, 100, 0, 359));
import React from 'react';

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

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

const describeSlice = (x, y, radius, startAngle, endAngle) => {

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

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

    const d = [
        "M", 0, 0, start.x, start.y,
        "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
    ].join(" ");

    return d;
};

const path = (degrees = 90, radius = 10) => {
    return describeSlice(0, 0, radius, 0, degrees) + 'Z';
};

export const Arc = (props) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
    <g transform="translate(150,150)" stroke="#000" strokeWidth="2">
        <path d={path(props.degrees, props.radius)} fill="#333"/>
    </g>

</svg>;

export default Arc;
  console.log(describeArc(255,255,220,30,180));
  console.log(describeArc(CenterX,CenterY,Radius,startAngle,EndAngle))
const angleInRadians = angleInDegrees => (angleInDegrees - 90) * (Math.PI / 180.0);

const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
    const a = angleInRadians(angleInDegrees);
    return {
        x: centerX + (radius * Math.cos(a)),
        y: centerY + (radius * Math.sin(a)),
    };
};

const arc = (x, y, radius, startAngle, endAngle) => {
    const fullCircle = endAngle - startAngle === 360;
    const start = polarToCartesian(x, y, radius, endAngle - 0.01);
    const end = polarToCartesian(x, y, radius, startAngle);
    const arcSweep = endAngle - startAngle <= 180 ? '0' : '1';

    const d = [
        'M', start.x, start.y,
        'A', radius, radius, 0, arcSweep, 0, end.x, end.y,
    ].join(' ');

    if (fullCircle) d.push('z');
    return d;
};
rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, xf, yf