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: enter image description here

Approximately what I get (they go too low): enter image description here

+3


source to share


2 answers


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.

DEMO

+2


source


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.

+1


source







All Articles