繁体   English   中英

贝塞尔曲线定时动画路径

[英]Bezier timed animation path

我正在尝试定义点的路径。 每个点都有一个x,y和时间。 然后,我想查询此路径并获取该时间点的当前位置。 让我分享一些伪代码。

point {x, y, time}


function initialisePath(point[] path) {
    ... // Create Bezier Path
}

function getXYAtTime(time) {
    return ... // Get interpolated point along the bezier path at the specified time
}

我正在尝试使用canvas标签在javascript中实现这一点。 但是,可以使用任何语言的示例。 有谁知道创建这种可查询路径的任何开源库(任何语言)?

注意:我一直在努力从DynApi项目了解此示例和代码,但是对于我较差的动画技巧来说,从该示例过渡到具有时间意识的路径是很困难的。

谢谢

圭多

贝塞尔曲线不仅具有起点和终点,而且还具有控制曲线形状的控制点 在您链接的DynApi演示中,端点标记为黄色,控制点标记为红色。

您的路径将是一系列Bézier曲线,这些曲线首尾相连。

因此,让我们使用您的伪代码,但是我们会将所有没有 .time属性的点都视为控制点。

function Path(points) {
    this.points = points;

    // Sanity check.
    if (points[0].time == undefined || points[points.length - 1].time == undefined)
        throw new Error("all control points must be between two real points");
}

Path.prototype.getXYAtTime = function (t) {
    var points = this.points;

    // First, see if t is out of range.
    if (t < points[0].time)
        return points[0];
    if (t > points[points.length - 1].time)
        return points[points.length - 1];

    // OK, t is in range. Find out which Bezier curve we're in.
    //
    // Specifically we want 'start' and 'stop' to be the indexes of two points
    // that each have a .time property, bracketing the current time t; and
    // all the points in between 'start' and 'stop' should be control points.
    //
    var start = 0, stop = points.length - 1;
    for (var i = 1; i < points.length; i++) {
        var p = points[i];
        if (t < p.time) {
            stop = i;
            break;
        }
        if (p.time != undefined)
            start = i;
    }
    var n = stop - start;

    // Adjust t to be in the range [0, 1).
    var t0 = points[start].time, t1 = points[stop].time;
    t = (t - t0) / (t1 - t0);
    var tInv = 1 - t;

    // Now calculate the current position in the curve.
    // Wikipedia says this is:
    //   sum for i = 0 to n of (n C i * (1 - t) ^ (n - i) * t ^ i * P[i])
    // 
    var x = 0, y = 0;
    for (var i = 0; i <= n; i++) {
        var p = points[start + i];
        var c = nCr(n, i) * Math.pow(1 - t, n - i) * Math.pow(t, i);
        x += c * p.x;
        y += c * p.y;
    }
    return {x: x, y: y};
}

// The number of k-combinations of a set of size n.
function nCr(n, k) {
    var z = 1;
    for (var i = 1; i <= k; i++)
        z *= (n + 1 - i) / i;
    return z;
}

这就是数学部分。 由您决定将其连接到画布上并使其移动。

这是您调用该方法的方式:

// Here's a Path consisting of a single Bezier curve.
var path = new Path([
    {x: 200, y: 150, time: 0},  // start point
    {x: 200, y: 500},           // 2 control points
    {x: 250, y: 100},
    {x: 500, y: 300, time: 50}  // end point
  ]);

var p = path.getXYAtTime(2.718);
alert(p.x + ", " + p.y);

贝塞尔曲线的控制点实际上就是您通过将每个端点处的所需速度矢量添加到端点而得到的。 例如,如果您要在点x0,y0处使用速度vx0,vy0,然后继续以速度vx1,vy1到达点x1,y1,则使用以下四个点定义贝塞尔曲线: (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1) (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1) (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1) (中间两个是您的控制点。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM