rysowanie łuków w js
Muszę rysować koncentryczne łuki różnych rozmiarów za pomocą Rafaela.js. Próbowałem zrozumieć kod za http://raphaeljs.com/polar-clock.html , co jest bardzo podobne do tego, czego chcę, ale, Bez komentarza, jest to dość trudne do zrozumienia.
Idealnie, potrzebowałbym funkcji, która tworzy ścieżkę, która znajduje się w określonej odległości od jakiegoś punktu środkowego, zaczyna się pod pewnym kątem, a kończy pod innym kątem.
7 answers
Ta odpowiedź jest ok, ale nie może być animowana. Wyrwałem Ci ważne rzeczy z zegara polarnego. Oto czerwony łuk, który ożywia wzrost. smacznego.
// 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");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-10 16:03:12
Oto Jak to zrobiłem. Poniższy kod pozwala określić kąt początkowy i końcowy, a także wewnętrzny i zewnętrzny promień (przydatne do robienia tych modnych wykresów kołowych w stylu pączka). Rozwiązanie nie polega na przybliżaniu krzywej za pomocą segmentów linii i może być animowane zgodnie z przykładem zegara wspomnianym w pierwotnym pytaniu.
Najpierw Utwórz swój obszar rysowania Raphael; poniżej Zakładamy div o id "raphael_paper" w pliku HTML:
var paper = Raphael("raphael_paper", 800, 800);
Do tego Rafała obiekt dodajemy Niestandardowy atrybut arc
, funkcję, która zajmuje środek okręgu( X i y), kąt początkowy, kąt końcowy, promień wewnętrzny i promień zewnętrzny:
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};
};
Teraz możemy użyć tego do narysowania łuków o określonej grubości, zaczynając i kończąc tam, gdzie chcemy, np.
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]});
Powinno to spowodować powstanie trzech szarych segmentów łuku z czerwonymi, niebieskimi i zielonymi obramowaniami 1px.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-17 15:15:48
Sam znalazłem odpowiedź. Po raz pierwszy pomyślałem o czymś fantazyjnym, obejmującym krzywe Beziera, ale to po prostu działa.
- > tworzy ścieżkę używając składni SVG path, która działa jak z Raphaelem
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];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-23 13:08:15
Aby usunąć jakieś zgadywanki z odpowiedzi user592699, jest to kompletny kod, który działa:
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-13 08:34:33
Dla tych, którzy chcą, aby łuk był wykonany z zamkniętą ścieżką, a nie obrysem, rozszerzyłem odpowiedź genkilabs, aby znaleźć rozwiązanie. W przypadkach, gdy trzeba podać zewnętrzny skok łuku, może to pomóc.
// 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");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 09:55:02
Można to również zrobić bez konieczności używania pętli. Poniżej można to osiągnąć i działa również z ujemnymi kątami.
Przekazać w obiekcie jako r . Kąty zaczynają się od 0 stopni, co jest wierzchołkiem okręgu, a nie prawo, jak wymieniono w kilku innych rozwiązaniach.
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]]);
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-11 04:46:31
Dostosowałem odpowiedź genkilabs do możliwości rotacji i inwersji. Również ilość wypełnionego Pierścienia została zmieniona na procent pojedynczej liczby. (Inwersja została zaadaptowana z tego posta ). Mam nadzieję, że to pomocne!
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,
};
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:24:17