etiqueta arc raphael vector-graphics bezier geometric-arc

raphael - arc - svg path d



Dibujo de arcos centrados en raphael js. (7)

Así es como lo he hecho. El siguiente código le permite especificar un ángulo de inicio y final, así como un radio interno y externo (útil para hacer esos gráficos circulares de estilo de dona). La solución no se basa en aproximar una curva con segmentos de línea y puede animarse según el ejemplo de reloj mencionado en la pregunta original.

Primero crea tu área de dibujo de Rafael; lo siguiente supone un div con id "raphael_paper" en su archivo HTML:

var paper = Raphael("raphael_paper", 800, 800);

a este objeto Raphael le agregamos un atributo de arc personalizado, una función que toma el centro de un círculo (coacciones xey), un ángulo inicial, un ángulo final, un radio interno y un radio externo:

paper.customAttributes.arc = function (centerX, centerY, startAngle, endAngle, innerR, outerR) { var radians = Math.PI / 180, largeArc = +(endAngle - startAngle > 180); // calculate the start and end points for both inner and outer edges of the arc segment // the -90s are about starting the angle measurement from the top get rid of these if this doesn''t suit your needs outerX1 = centerX + outerR * Math.cos((startAngle-90) * radians), outerY1 = centerY + outerR * Math.sin((startAngle-90) * radians), outerX2 = centerX + outerR * Math.cos((endAngle-90) * radians), outerY2 = centerY + outerR * Math.sin((endAngle-90) * radians), innerX1 = centerX + innerR * Math.cos((endAngle-90) * radians), innerY1 = centerY + innerR * Math.sin((endAngle-90) * radians), innerX2 = centerX + innerR * Math.cos((startAngle-90) * radians), innerY2 = centerY + innerR * Math.sin((startAngle-90) * radians); // build the path array var path = [ ["M", outerX1, outerY1], //move to the start point ["A", outerR, outerR, 0, largeArc, 1, outerX2, outerY2], //draw the outer edge of the arc ["L", innerX1, innerY1], //draw a line inwards to the start of the inner edge of the arc ["A", innerR, innerR, 0, largeArc, 0, innerX2, innerY2], //draw the inner arc ["z"] //close the path ]; return {path: path}; };

ahora podemos usar esto para dibujar arcos de un espesor específico, comenzando y terminando donde queramos, por ejemplo.

var redParams = {stroke: "#f00", "stroke-width": 1, fill:"#eee"}, greenParams = {stroke: "#0f0", "stroke-width": 1, fill:"#eee"}, blueParams = {stroke: "#00f", "stroke-width": 1, fill:"#eee"}, cx = 300, cy = 300, innerRadius = 100, outerRadius = 250, var red = paper.path().attr(redParams).attr({arc: [cx, cy, 0, 90, innerRadius, outerRadius]}); var green = paper.path().attr(greenParams).attr({arc: [cx, cy, 270, 320, innerRadius, outerRadius]}); var blue = paper.path().attr(blueParams).attr({arc: [cx, cy, 95, 220, innerRadius, outerRadius]});

Esto debería dar como resultado tres segmentos de arco gris con bordes de 1px rojo, azul y verde.

Necesito dibujar arcos concéntricos de varios tamaños usando raphael.js. Intenté entender el código detrás de http://raphaeljs.com/polar-clock.html , que es muy similar a lo que quiero, pero, sin comentarios, es bastante difícil de entender.

Idealmente, necesitaría una función que cree una trayectoria que se encuentre a una distancia dada de algún punto central, comience en algún ángulo y termine en otro ángulo.


En realidad encontré la respuesta yo mismo. Primero pensé en algo sofisticado que involucraba curvas de Bézier, pero esto simplemente funciona.

-> crea una ruta usando la sintaxis de la ruta SVG, que funciona como es con Raphael

function arc(center, radius, startAngle, endAngle) { angle = startAngle; coords = toCoords(center, radius, angle); path = "M " + coords[0] + " " + coords[1]; while(angle<=endAngle) { coords = toCoords(center, radius, angle); path += " L " + coords[0] + " " + coords[1]; angle += 1; } return path; } function toCoords(center, radius, angle) { var radians = (angle/180) * Math.PI; var x = center[0] + Math.cos(radians) * radius; var y = center[1] + Math.sin(radians) * radius; return [x, y]; }


Esa respuesta está bien, pero no puede ser animada. Saqué las cosas importantes del reloj polar para ti. Aquí hay un arco rojo que anima el crecimiento. disfrutar.

// Custom Arc Attribute, position x&y, value portion of total, total value, Radius var archtype = Raphael("canvas", 200, 100); archtype.customAttributes.arc = function (xloc, yloc, value, total, R) { var alpha = 360 / total * value, a = (90 - alpha) * Math.PI / 180, x = xloc + R * Math.cos(a), y = yloc - R * Math.sin(a), path; if (total == value) { path = [ ["M", xloc, yloc - R], ["A", R, R, 0, 1, 1, xloc - 0.01, yloc - R] ]; } else { path = [ ["M", xloc, yloc - R], ["A", R, R, 0, +(alpha > 180), 1, x, y] ]; } return { path: path }; }; //make an arc at 50,50 with a radius of 30 that grows from 0 to 40 of 100 with a bounce var my_arc = archtype.path().attr({ "stroke": "#f00", "stroke-width": 14, arc: [50, 50, 0, 100, 30] }); my_arc.animate({ arc: [50, 50, 40, 100, 30] }, 1500, "bounce");


He adaptado la respuesta de genkilabs para incluir habilidades de rotación e inversión. Además, la cantidad de anillo que se llena se cambió a un porcentaje de un solo número. (La inversión fue adaptada de este post ). Espero que sea de ayuda!

paper.customAttributes.arc = function (xloc, yloc, percent, rad, rot, invert) { var alpha = 3.6 * percent, a = (90 - alpha) * Math.PI / 180, x = xloc + rad * Math.cos(a), y = yloc - rad * Math.sin(a), path; if (invert) { x = xloc - rad * Math.cos(a); } if (percent >= 100) { path = [ ["M", xloc, yloc - rad], ["A", rad, rad, 0, 1, 1, xloc - 0.01, yloc - rad] ]; } else { path = [ ["M", xloc, yloc - rad], ["A", rad, rad, 0, +(alpha > 180), +(!invert), x, y] ]; } return { path: path, transform: "r"+rot+","+xloc+","+yloc, }; };


Para aquellos que desean que el arco se realice con una trayectoria cerrada y no con un trazo, he extendido la respuesta de genkilabs para hacer una solución. En los casos en los que necesite aplicar un trazo externo a su arco, esto podría ayudar.

// Custom Arc Attribute, position x&y, value portion of total, total value, Radius, width var archtype = Raphael("canvas", 200, 100); archtype.customAttributes.arc = function (xloc, yloc, value, total, R, width) { if(!width) width = R * 0.4; var alpha = 360 / total * value, a = (90 - alpha) * Math.PI / 180, w = width / 2, r1 = R + w, r2 = R - w, x1 = xloc + r1 * Math.cos(a), y1 = yloc - r1 * Math.sin(a), x2 = xloc + r2 * Math.cos(a), y2 = yloc - r2 * Math.sin(a), path; if (total == value) { path = [ ["M", xloc, yloc - r1], ["A", r1, r1, 0, 1, 1, xloc - 0.01, yloc - r1], ["Z"], ["M", xloc - 0.01, yloc - r2], ["A", r2, r2, 0, 1, 0, xloc, yloc - r2], ["Z"] ]; } else { path = [ ["M", xloc, yloc - r1], ["A", r1, r1, 0, +(alpha > 180), 1, x1, y1], ["L", x2, y2], ["A", r2, r2, 0, +(alpha > 180), 0, xloc, yloc - r2], ["L", xloc, yloc - r1], ["Z"] ]; } return { path: path }; }; //make an arc at 50,50 with a radius of 30 that grows from 0 to 40 of 100 with a bounce var my_arc = archtype.path().attr({ "fill": "#00f", "stroke": "#f00", "stroke-width": 5, arc: [50, 50, 0, 100, 30] }); my_arc.animate({ arc: [50, 50, 40, 100, 30] }, 1500, "bounce");

JSFiddle


Solo para eliminar algunas conjeturas de la respuesta del usuario 592699, este es el código completo que funciona:

<script src="raphael.js"></script> <script> var paper = Raphael(20, 20, 320, 320); function arc(center, radius, startAngle, endAngle) { angle = startAngle; coords = toCoords(center, radius, angle); path = "M " + coords[0] + " " + coords[1]; while(angle<=endAngle) { coords = toCoords(center, radius, angle); path += " L " + coords[0] + " " + coords[1]; angle += 1; } return path; } function toCoords(center, radius, angle) { var radians = (angle/180) * Math.PI; var x = center[0] + Math.cos(radians) * radius; var y = center[1] + Math.sin(radians) * radius; return [x, y]; } paper.path(arc([100, 100], 80, 0, 270)); // draw an arc // centered at (100, 100), // radius 80, starting at degree 0, // beginning at coordinate (80, 0) // which is relative to the center // of the circle, // going clockwise, until 270 degree </script>


También puedes hacer esto sin tener que usar bucles. Lo siguiente logra esto y funciona con ángulos negativos también.

Pasar en un objeto de Rafael como r . Los ángulos comienzan con 0 grados, que es la parte superior del círculo en lugar de la derecha, como se indica en un par de otras soluciones.

function drawArc(r, centerX, centerY, radius, startAngle, endAngle) { var startX = centerX+radius*Math.cos((90-startAngle)*Math.PI/180); var startY = centerY-radius*Math.sin((90-startAngle)*Math.PI/180); var endX = centerX+radius*Math.cos((90-endAngle)*Math.PI/180); var endY = centerY-radius*Math.sin((90-endAngle)*Math.PI/180); var flg1 = 0; if (startAngle>endAngle) flg1 = 1; else if (startAngle<180 && endAngle<180) flg1 = 0; else if (startAngle>180 && endAngle>180) flg1 = 0; else if (startAngle<180 && endAngle>180) flg1 = 0; // edited for bugfix here, previously this was 1 else if (startAngle>180 && endAngle<180) flg1 = 1; return r.path([[''M'',startX, startY],[''A'',radius,radius,0,flg1,1,endX,endY]]); };