Dibujo circular con la ruta de arco de SVG

La siguiente ruta SVG puede dibujar el 99,99% de un círculo: (pruébalo en http://jsfiddle.net/DFhUF/46/ y mira si ves 4 arcos o solo 2, pero ten en cuenta que si se trata de IE, se procesa en VML, no SVG, pero tienen el problema similar)

M 100 100 a 50 50 0 1 0 0.00001 0 

Pero cuando es 99.99999999% de un círculo, ¿nada se mostrará en absoluto?

 M 100 800 a 50 50 0 1 0 0.00000001 0 

Y eso es lo mismo con el 100% de un círculo (sigue siendo un arco, ¿no ?, solo un arco muy completo)

 M 100 800 a 50 50 0 1 0 0 0 

¿Cómo puede ser arreglado? La razón es que utilizo una función para dibujar un porcentaje de un arco, y si necesito un “caso especial” un 99.9999% o 100% de arco para usar la función del círculo, sería una tontería.

Nuevamente, un caso de prueba en jsfiddle usando RaphaelJS está en http://jsfiddle.net/DFhUF/46/
(Y si es VML en IE 8, incluso el segundo círculo no se mostrará … debes cambiarlo a 0.01)


Actualizar:

Esto es porque estoy renderizando un arco para un puntaje en nuestro sistema, por lo que 3.3 puntos obtienen 1/3 de un círculo. 0.5 obtiene medio círculo, y 9.9 puntos obtienen 99% de un círculo. ¿Pero qué pasa si hay puntajes que son 9.99 en nuestro sistema? ¿Tengo que verificar si está cerca del 99.999% de un círculo y usar una función de arc o una función de circle consecuencia? Entonces, ¿qué pasa con un puntaje de 9.9987? ¿Cuál usar? Es ridículo tener que saber qué tipo de puntajes se asignarán a un “círculo demasiado completo” y cambiar a una función de círculo, y cuando es “un 99.9%” de un círculo o un puntaje de 9.9987, entonces use la función de arco. .

Lo mismo para el arco de XAML. ¡Solo cierra el arco del 99.99% con una Z y tienes un círculo!

Sé que es un poco tarde en el juego, pero recordé esta pregunta cuando era nueva y tuve un dilema similar, y accidentalmente encontré la solución “correcta”, si alguien todavía está buscando una:

  

En otras palabras, esto:

  

se puede lograr como un camino con esto:

   

El truco es tener dos arcos, el segundo retomando el primero y usando el diámetro negativo para volver al punto de inicio del arco original.

La razón por la que no se puede hacer como un círculo completo en un arco (y solo estoy especulando) es porque le estarías diciendo que dibuje un arco propio (digamos 150,150) a sí mismo (150,150), que rinde como “oh, ya estoy allí, no es necesario arco”).

Los beneficios de la solución que estoy ofreciendo son:

  1. es fácil traducir de un círculo directamente a un camino, y
  2. no hay superposición en las dos líneas de arco (lo que puede causar problemas si usa marcadores o patrones, etc.). Es una línea continua y limpia, aunque dibujada en dos partes.

Nada de esto importaría si solo permitieran que los caminos de texto aceptaran formas. Pero creo que están evitando esa solución ya que los elementos de forma como el círculo técnicamente no tienen un punto de “inicio”.

Demostración jsfiddle: http://jsfiddle.net/crazytonyi/mNt2g/

Actualizar:

Si está utilizando la ruta para una referencia de textPath y desea que el texto se represente en el borde exterior del arco, usaría exactamente el mismo método pero cambiaría la bandera de barrido de 0 a 1 para que trate el exterior de el camino como la superficie en vez del interior (piense en 1,0 como alguien sentado en el centro y dibujando un círculo alrededor de sí mismo, mientras que 1,1 como alguien que camina alrededor del centro a una distancia de radio y arrastrando su tiza junto a ellos, si eso es alguna ayuda). Aquí está el código como arriba pero con el cambio:

  

Consulte la solución de Anthony aquí es una función para obtener la ruta:

 function circlePath(cx, cy, r){ return 'M '+cx+' '+cy+' m -'+r+', 0 a '+r+','+r+' 0 1,0 '+(r*2)+',0 a '+r+','+r+' 0 1,0 -'+(r*2)+',0'; } 

Un enfoque totalmente diferente:

En lugar de jugar con las rutas para especificar un arco en svg, también puede tomar un elemento de círculo y especificar un trazo-dasharray, en pseudo código:

 with $score between 0..1, and pi = 3.141592653589793238 $length = $score * 2 * pi * $r $max = 7 * $r (ie well above 2*pi*r)  

Su simplicidad es la principal ventaja sobre el método de múltiples trayectorias de arco (por ejemplo, al crear scripts solo se conecta un valor y se termina con cualquier longitud de arco)

El arco comienza en el punto más a la derecha y se puede desplazar utilizando una transformación de rotación.

Nota: Firefox tiene un error extraño donde las rotaciones de más de 90 grados o más son ignoradas. Entonces, para comenzar el arco desde la parte superior, use:

  

Adobe Illustrator utiliza curvas de bezier como SVG, y para círculos crea cuatro puntos. Puedes crear un círculo con dos comandos de arco elíptico … pero luego para un círculo en SVG usaría un 🙂

Es una buena idea usar dos comandos de arco para dibujar un círculo completo.

por lo general, uso el elipse o el elemento del círculo para dibujar un círculo completo.

Escrito como una función, se ve así:

 function getPath(cx,cy,r){ return "M" + cx + "," + cy + "m" + (-r) + ",0a" + r + "," + r + " 0 1,0 " + (r * 2) + ",0a" + r + "," + r + " 0 1,0 " + (-r * 2) + ",0"; } 

Sobre la base de las respuestas de Anthony y Anton incorporé la capacidad de rotar el círculo generado sin afectar su apariencia general. Esto es útil si está usando la ruta para una animación y necesita controlar dónde comienza.

 function(cx, cy, r, deg){ var theta = deg*Math.PI/180, dx = r*Math.cos(theta), dy = -r*Math.sin(theta); return "M "+cx+" "+cy+"m "+dx+","+dy+"a "+r+","+r+" 0 1,0 "+-2*dx+","+-2*dy+"a "+r+","+r+" 0 1,0 "+2*dx+","+2*dy; } 

Para aquellos como yo, que estábamos buscando una atributos de elipse para la conversión de ruta:

 const ellipseAttrsToPath = (rx,cx,ry,cy) => `M${cx-rx},${cy}a${rx},${ry} 0 1,0 ${rx*2},0a${rx},${ry} 0 1,0 -${rx*2},0` 

Hice un jsfiddle para hacerlo aquí:

 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; } console.log(describeArc(255,255,220,134,136)) 

enlazar

todo lo que tiene que hacer es cambiar la entrada de console.log y obtener el resultado en la consola

Otra forma sería usar dos curvas cúbicas de Bezier. Eso es para gente de iOS que usa pocketSVG que no reconoce el parámetro svg arc.

C x1 y1, x2 y2, xy (o c dx1 dy1, dx2 dy2, dx dy)

Curva cúbica de Bezier

El último conjunto de coordenadas aquí (x, y) es donde desea que termine la línea. Los otros dos son puntos de control. (x1, y1) es el punto de control para el inicio de su curva, y (x2, y2) para el punto final de su curva.

  

Estas respuestas son demasiado complicadas.

Una forma más sencilla de hacerlo sin crear dos arcos o convertir a diferentes sistemas de coordenadas …

Esto supone que su área de canvas tiene ancho w altura h .

 `M${w*0.5 + radius},${h*0.5} A${radius} ${radius} 0 1 0 ${w*0.5 + radius} ${h*0.5001}` 

Simplemente use la bandera de “arco largo”, de modo que se llene la bandera completa. Luego haz los arcos 99.9999% del círculo completo. Visualmente es lo mismo. Evite la bandera de barrido comenzando el círculo en el punto más a la derecha del círculo (un radio directamente horizontal desde el centro).

¡Estos ejemplos son muy complicados!

Simplemente haz esto con los literales de plantilla es6.

Una forma más sencilla de hacerlo sin crear dos arcos.

Esto supone que su área de canvas tiene ancho wy altura h.

 `M${w*0.5 + radius},${h*0.5} A${radius} ${radius} 0 1 0 ${w*0.5 + radius} ${h*0.5001}` 

Simplemente use la bandera de “arco largo”, de modo que se llene la bandera completa. Luego haz los arcos 99.9999% del círculo completo. Visualmente es lo mismo. Evite la bandera de barrido comenzando el círculo en el punto más a la derecha del círculo (un radio directamente horizontal desde el centro).