68 votos

Cómo calcular el SVG Trazado de un arco (de un círculo)

Dado un círculo con centro en (200,200), radio de 25, ¿cómo se dibuja un arco de 270 grados a 135 grados y uno que va de 270 a 45 grados?

0 grado medio es a la derecha en el eje x (el lado derecho) (es decir, 3 o' posición del reloj) De 270 grados significa que es la posición de las 12 horas, y el 90 significa que es 6 en punto de posición

De manera más general, ¿qué es una ruta de acceso para un arco por parte de un círculo con

x, y, r, d1, d2, direction

significado

center (x,y), radius r, degree_start, degree_end, direction

103voto

opsb Puntos 6860

La expansión en @wdebeaum la gran respuesta, he aquí un método para la generación de un arqueadas ruta:

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 arcSweep = endAngle - startAngle <= 180 ? "0" : "1";

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

    return d;       
}

el uso de

document.getElementById("arc1").setAttribute("d", describeArc(200, 400, 100, 0, 180));

y en el html

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

87voto

wdebeaum Puntos 2116

Desea utilizar la elíptica Arc comando. Por desgracia para usted, esto requiere especificar las coordenadas Cartesianas (x, y) de los puntos de inicio y final en lugar de las coordenadas polares (radio, ángulo) que tienen, por lo que tienen que hacer algo de matemáticas. Aquí está una función de JavaScript que se debe de trabajar (aunque yo no lo he probado), y que espero es bastante auto-explicativo:

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];
}

Que los ángulos corresponden a que el reloj de posiciones dependen del sistema de coordenadas; sólo de intercambio y/o negar el pecado/cos términos como sea necesario.

La orden del arco tiene los siguientes parámetros:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y

Para el primer ejemplo:

rx=ry=25 y x-axis-rotation=0, ya que quieres un círculo y no de una elipse. Usted puede calcular las coordenadas de inicio (la cual debe Move a) y terminando coordenadas (x, y) utilizando la función anterior, con un rendimiento (200, 175) y sobre (182.322, 217.678), respectivamente. Dadas estas limitaciones hasta el momento, hay en realidad cuatro arcos que podrían ser atraídos, por lo que las dos banderas seleccionar uno de ellos. Supongo que usted probablemente desea dibujar un arco pequeño (significado large-arc-flag=0), en la dirección de la disminución de ángulo (significado sweep-flag=0). Todos juntos, el SVG ruta de acceso es:

M 200 175 A 25 25 0 0 0 182.322 217.678

Para el segundo ejemplo (suponiendo que significa que van en la misma dirección, y por lo tanto un gran arco), el SVG ruta de acceso es:

M 200 175 A 25 25 0 1 0 217.678 217.678

De nuevo, no he probado estos.

8voto

Ahtenus Puntos 136

He modificado ligeramente la respuesta de opsb y de hecho en el soporte de relleno para el círculo del sector. http://codepen.io/anon/pen/AkoGx

JS

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 arcSweep = endAngle - startAngle <= 180 ? "0" : "1";

    var d = [
        "M", start.x, start.y, 
        "A", radius, radius, 0, arcSweep, 0, end.x, end.y,
        "L", x,y,
        "L", start.x, start.y
    ].join(" ");

    return d;       
}

document.getElementById("arc1").setAttribute("d", describeArc(200, 400, 100, 0, 220));

HTML

<svg>
  <path id="arc1" fill="orange" stroke="#446688" stroke-width="0" />
</svg>

1voto

Wiley Puntos 31

El original polarToCartesian función de wdebeaum es correcta:

var angleInRadians = angleInDegrees * Math.PI / 180.0;

El cambio de puntos de inicio y final mediante el uso de:

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

Es confuso (para mí) porque esto va a invertir el barrido de la bandera. El uso de:

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

con el barrido de bandera = "0" dibuja "normal" en sentido antihorario arcos, que creo que es más sencillo. Ver https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X