illustrator formato examples svg

formato - svg illustrator



Cómo calcular el SVG Path para un arco(de un círculo) (12)

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

0 grados significa que está justo en el eje x (el lado derecho) (lo que significa que es la posición 3 en punto) 270 grados significa que es la posición de las 12 en punto, y 90 significa que es la posición de las 6 en punto

De manera más general, ¿cuál es la ruta de un arco para formar parte de un círculo con

x, y, r, d1, d2, direction

sentido

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


Una imagen y algo de Python

Solo para aclarar mejor y ofrecer otra solución. A comando Arc [ A ] utiliza la posición actual como punto de partida, por lo que Moveto debe usar el Moveto [M].

Entonces los parámetros de Arc son los siguientes:

rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, xf, yf

Si definimos por ejemplo el siguiente archivo svg:

<svg width="5cm" height="5cm" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" version="1.1">

El siguiente código le dará este resultado:

<g stroke="none" fill="lime"> <path d=" M 250 250 A 100 100 0 0 0 450 250 Z"/> </g>

Establecerá el punto de inicio con M el punto final con los parámetros xf e yf de A

Estamos buscando círculos, por lo que establecemos que rx igual a hacer, básicamente ahora tratará de encontrar todo el círculo de radio rx que se cruza con el punto inicial y final.

import numpy as np def write_svgarc(xcenter,ycenter,r,startangle,endangle,output=''arc.svg''): if startangle > endangle: raise ValueError("startangle must be smaller than endangle") if endangle - startangle < 360: large_arc_flag = 0 radiansconversion = np.pi/180. xstartpoint = xcenter + r*np.cos(startangle*radiansconversion) ystartpoint = ycenter - r*np.sin(startangle*radiansconversion) xendpoint = xcenter + r*np.cos(endangle*radiansconversion) yendpoint = ycenter - r*np.sin(endangle*radiansconversion) #If we want to plot angles larger than 180 degrees we need this if endangle - startangle > 180: large_arc_flag = 1 with open(output,''a'') as f: f.write(r"""<path d=" """) f.write("M %s %s" %(xstartpoint,ystartpoint)) f.write("A %s %s 0 %s 0 %s %s" %(r,r,large_arc_flag,xendpoint,yendpoint)) f.write("L %s %s" %(xcenter,ycenter)) f.write(r"""Z"/>""" ) else: with open(output,''a'') as f: f.write(r"""<circle cx="%s" cy="%s" r="%s"/>""" %(xcenter,ycenter,r))

Puedes tener una explicación más detallada en esta publicación que escribí.


Ampliando la gran respuesta de @ wdebeaum, aquí hay un método para generar una ruta en arco:

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

usar

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

y en tu html

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

Demo en vivo


Componente ReactJS basado en la respuesta seleccionada:

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;


Desea utilizar el comando A rc elíptico . Desafortunadamente para usted, esto requiere que especifique las coordenadas cartesianas (x, y) de los puntos de inicio y final en lugar de las coordenadas polares (radio, ángulo) que tiene, por lo que debe hacer algunas operaciones matemáticas. Aquí hay una función de JavaScript que debería funcionar (aunque no la he probado), y espero que sea bastante fácil de explicar:

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

Qué ángulos corresponden a qué posiciones de reloj dependerán del sistema de coordenadas; simplemente intercambie y / o niegue los términos sin / cos según sea necesario.

El comando de arco tiene estos parámetros:

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

Para su primer ejemplo:

rx = ry = 25 y x-axis-rotation = 0, ya que quiere un círculo y no una elipse. Puede calcular tanto las coordenadas iniciales (a las que debe M ove) como las coordenadas finales (x, y) utilizando la función anterior, rindiendo (200, 175) y aproximadamente (182.322, 217.678), respectivamente. Teniendo en cuenta estas limitaciones hasta ahora, en realidad hay cuatro arcos que se pueden dibujar, por lo que las dos banderas seleccionan uno de ellos. Supongo que probablemente quieras dibujar un pequeño arco (que significa large-arc-flag = 0), en la dirección del ángulo decreciente (que significa sweep-flag = 0). En conjunto, la ruta SVG es:

M 200 175 A 25 25 0 0 0 182.322 217.678

Para el segundo ejemplo (suponiendo que te refieres a ir en la misma dirección, y por lo tanto un gran arco), la ruta SVG es:

M 200 175 A 25 25 0 1 0 217.678 217.678

De nuevo, no los he probado.

(edit 2016-06-01) Si, como @clocksmith, se pregunta por qué eligieron esta API, eche un vistazo a las notas de implementación . Describen dos posibles parametrizaciones de arco, "parametrización de punto final" (la que eligieron) y "parametrización central" (que es como lo que utiliza la pregunta). En la descripción de "parametrización de punto final" dicen:

Una de las ventajas de la parametrización de punto final es que permite una sintaxis de ruta consistente en la que todos los comandos de ruta terminan en las coordenadas del nuevo "punto actual".

Así que, básicamente, es un efecto secundario de los arcos considerados como parte de una ruta más grande en lugar de su propio objeto separado. Supongo que si su renderizador SVG está incompleto, podría omitir los componentes de ruta que no sabe cómo renderizar, siempre que sepa cuántos argumentos toman. O tal vez permite la representación paralela de diferentes fragmentos de una ruta con muchos componentes. O tal vez lo hicieron para asegurarse de que los errores de redondeo no se acumularan a lo largo de una ruta compleja.

Las notas de implementación también son útiles para la pregunta original, ya que tienen más pseudocódigo matemático para convertir entre las dos parametrizaciones (que no me di cuenta cuando escribí esta respuesta por primera vez).


Esta es una vieja pregunta, pero encontré el código útil y me ahorró tres minutos para pensar :) Así que estoy agregando una pequeña expansión a la respuesta de @opsb .

Si desea convertir este arco en una porción (para permitir el llenado), podemos modificar el código ligeramente:

function describeArc(x, y, radius, spread, startAngle, endAngle){ var innerStart = polarToCartesian(x, y, radius, endAngle); var innerEnd = polarToCartesian(x, y, radius, startAngle); var outerStart = polarToCartesian(x, y, radius + spread, endAngle); var outerEnd = polarToCartesian(x, y, radius + spread, startAngle); var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1"; var d = [ "M", outerStart.x, outerStart.y, "A", radius + spread, radius + spread, 0, largeArcFlag, 0, outerEnd.x, outerEnd.y, "L", innerEnd.x, innerEnd.y, "A", radius, radius, 0, largeArcFlag, 1, innerStart.x, innerStart.y, "L", outerStart.x, outerStart.y, "Z" ].join(" "); return d; } 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)) }; } var path = describeArc(150, 150, 50, 30, 0, 50) document.getElementById("p").innerHTML = path document.getElementById("path").setAttribute(''d'',path)

<p id="p"> </p> <svg width="300" height="300" style="border:1px gray solid"> <path id="path" fill="blue" stroke="cyan"></path> </svg>

y ahí tienes!


La función original polarToCartesian de wdebeaum es correcta:

var angleInRadians = angleInDegrees * Math.PI / 180.0;

Invertir los puntos de inicio y final utilizando:

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

Es confuso (para mí) porque esto invertirá la bandera de barrido. Utilizando:

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

con la barra de barrido = "0" dibuja arcos "normales" en sentido antihorario, lo que creo que es más directo. Ver https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths


Las respuestas de @ opsb son claras, pero el punto central no es preciso, además, como señaló @Jithin, si el ángulo es 360, entonces no se dibuja nada.

@Jithin solucionó el problema de 360, pero si seleccionó menos de 360 ​​grados, obtendrá una línea que cierra el ciclo de arco, que no es necesario.

Lo arreglé y agregué algunas animaciones en el siguiente código:

function myArc(cx, cy, radius, max){ var circle = document.getElementById("arc"); var e = circle.getAttribute("d"); var d = " M "+ (cx + radius) + " " + cy; var angle=0; window.timer = window.setInterval( function() { var radians= angle * (Math.PI / 180); // convert degree to radians var x = cx + Math.cos(radians) * radius; var y = cy + Math.sin(radians) * radius; d += " L "+x + " " + y; circle.setAttribute("d", d) if(angle==max)window.clearInterval(window.timer); angle++; } ,5) } myArc(110, 110, 100, 360);

<svg xmlns="http://www.w3.org/2000/svg" style="width:220; height:220;"> <path d="" id="arc" fill="none" stroke="red" stroke-width="2" /> </svg>


Modifiqué ligeramente la respuesta de opsb y realicé el relleno de soporte para el sector de círculo. 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>


Quería comentar la respuesta de @Ahtenus, específicamente sobre Ray Hulha, comentando que el codepen no muestra ningún arco, pero mi reputación no es lo suficientemente alta.

La razón de que este codepen no funcione es que su html es defectuoso con un ancho de trazo de cero.

Lo arreglé y agregué un segundo ejemplo aquí: http://codepen.io/AnotherLinuxUser/pen/QEJmkN .

El html:

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

El CSS relevante:

svg { width : 500px; height : 500px; } path { stroke-width : 5; stroke : lime; fill : #151515; }

El javascript:

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


Una ligera modificación a la respuesta de @ opsb. No podemos dibujar un círculo completo con este método. es decir, si damos (0, 360) no dibujará nada en absoluto. Entonces, se hizo una pequeña modificación para arreglar esto. Podría ser útil mostrar puntuaciones que a veces alcanzan el 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));


Versión ES6:

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


puede usar el código JSFiddle que hice para la respuesta anterior:

https://jsfiddle.net/tyw6nfee/

todo lo que necesita hacer es cambiar el código de la última línea de console.log y darle su propio parámetro:

console.log(describeArc(255,255,220,30,180)); console.log(describeArc(CenterX,CenterY,Radius,startAngle,EndAngle))