Reputation: 72405
I want to morph an arbitrary shape into a circle in Raphael, and I don't want excessive distortion, so I'm counting the nodes within the original path and creating a new path with the same number of nodes.
So far I've been able to arrange the new path into a polygon with the same number of nodes, but my math fails me when I want to adjust the cubic bezier points to accomplish a circle. I know I should calculate the tangent, but I'm not sure how to proceed. Here is my code:
var path, paper, circle, radius;
radius = 150;
paper = Raphael("canvas", radius*4, radius*4);
path = drawCircle(6) //can be any number
function drawCircle(nodes){
newPath = [];
for(x=0; x<nodes; x++) {
deg = (x/nodes)*360;
if(x==0) {
newPath.push("M " + Math.sin(deg*Math.PI/180)*radius + " " + Math.cos(deg*Math.PI/180)*radius);
}
else {
newPath.push(
"C " + Math.sin(deg*Math.PI/180)*radius
+ " " + Math.cos(deg*Math.PI/180)*radius
+ " " + Math.sin(deg*Math.PI/180)*radius
+ " " + Math.cos(deg*Math.PI/180)*radius
+ " " + Math.sin(deg*Math.PI/180)*radius
+ " " + Math.cos(deg*Math.PI/180)*radius
)
}
}
newPath.push("Z")
console.log(newPath)
paper.path(newPath).attr({"fill": "#000"}).translate(200, 200)
}
Here is a jsfiddle to try it out: http://jsfiddle.net/zeYtT/
Upvotes: 0
Views: 1041
Reputation: 11
the 'correct' way is to use cos for x, and y for sin. i compare the actual shapes of the letters (cos -> o -> x and sin -> i -> y) to remember it :)
Upvotes: 1
Reputation: 32878
Here's the corrected code. Note that you can use the arc path command rather than the curve command in SVG. Note also that the code below treats the first node and the last node as equal, giving it the appearance that it generates one extra node. This is assuming that all your arbitrary shapes are closed, that is, their first node and last node are equal, which can't be assured simply by the "close path" command (Z).
var path, paper, circle, radius;
radius = 150;
paper = Raphael("canvas", radius * 4, radius * 4);
path = drawCircle(8) //can be any number
function drawCircle(nodes) {
var newPath = []
for (var i = 0; i <= nodes; i++) {
var deg = (i*1.0 / nodes) * 360;
var x = Math.cos(deg * Math.PI / 180) * radius
var y = Math.sin(deg * Math.PI / 180) * radius
if (newPath == 0) newPath.push("M " + x + " " + y)
else newPath.push("A " + (radius) + "," + (radius) + ",0,0,1," + x + "," + y)
}
newPath.push("Z")
console.log(newPath)
paper.path(newPath).attr({
"fill": "#000"
}).translate(200, 200)
}
Upvotes: 2