How do I calculate the arc of a 1/4 circle to move (Bezier curve)?
I am using JQuery.path to traverse an object in a bezier curve. When the element is clicked, I can determine the start and end points. How to calculate the angle and length so that the element moves from point A to point B in an arc so that 1/4 of the circle intersects the start and end points?
I essentially want it to move along a curve that never goes below the starting position y
and is never to the left of the end x
.
var path = {
start: {
x: currentLeft,
y: currentTop,
angle: ????, //Don't know how to calculate this
length: ???? //Don't know how to calculate this
},
end: {
x: endLeft,
y: endTop,
angle: ????, //Don't know how to calculate this
length: ???? //Don't know how to calculate this
}
};
jQuery(myElement).animate(
{
path: new jQuery.path.bezier(path)
}
);
Approx. what I want:
Approximately what I get (they go too low):
source to share
The generalized solution is a little tricky because it has to handle diagonal movements in each of the four diagonal directions, horizontal and vertical.
First, you need a couple of useful features:
function r2d(x) {
/* radians to degrees */
return x * 180 / Math.PI;
}
function smaller(x, y) {
/* returns the closer of x|y to zero */
var x_ = Math.abs(x);
var y_ = Math.abs(y);
return (Math.min(x_, y_) === x_) ? x : y;
}
The main function now anim
accepts a jQuery object (containing the element of interest) and an object end
(with .left and .top properties).
function anim($el, end) {
var current = $el.position();
var slope1 = (end.top - current.top) / (end.left - current.left);
var slope2 = 1 / slope1;
var endAngle = r2d(Math.atan(smaller(slope1, slope2)));
var startAngle = -endAngle;
var length = 1/3; //Vary between 0 and 1 to affect the path curvature. Also, try >1 for an interesting effect.
//For debugging
$("#endAngle").text(endAngle);
$("#startAngle").text(startAngle);
$("#length").text(length);
var path = {
start: {
x: current.left,
y: current.top,
angle: startAngle,
length: length
},
end: {
x: end.left,
y: end.top,
angle: endAngle,
length: length
}
};
$el.animate({ path: new jQuery.path.bezier(path) });
}
The calculation is endAngle
quite simple for each individual case (four diagonals, horizontal and vertical), but a bit tricky for a generalized solution. It took me a while to develop what worked in all cases.
source to share
If "what you want" is really what you want, i.e. departure and arrival at 90 degrees, then we can solve this problem almost instantly:
p_start = { X:..., Y:... }
p_end = { X:..., Y:... }
dx = p_end.X - p_start.X
dy = p_end.Y - p_start.Y
control_1 = { X: p_start.X, Y: p_start.Y + 0.55228 * dy }
control_2 = { X: p_end.X - 0.55228 * dx, Y: p_end.Y }
And done. Basically, we pretend that the start and end points lie on the circle, and the computer controls the points so that the resulting Bezier curve has a minimum error along the quarter circular arc.
In terms of angles, the origin is always at an angle of π / 2, and the arrival at the end points is always at an angle of 0.
source to share