简体   繁体   English

贝塞尔曲线定时动画路径

[英]Bezier timed animation path

I'm trying to define a path of points. 我正在尝试定义点的路径。 Each point has an x, y, and time. 每个点都有一个x,y和时间。 I then want to query this path and get the current position at that point in time. 然后,我想查询此路径并获取该时间点的当前位置。 Let me share some pseudo code. 让我分享一些伪代码。

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
}

I'm trying to implement this in javascript using the canvas tag. 我正在尝试使用canvas标签在javascript中实现这一点。 However a sample in any language will do. 但是,可以使用任何语言的示例。 Does anyone know any open source library (in any language) that creates this kind of queriable path?? 有谁知道创建这种可查询路径的任何开源库(任何语言)?

Note: I've been trying to get my head around this sample and code from the DynApi project but moving from this sample to a time aware path is a stretch for my poor animational skills. 注意:我一直在努力从DynApi项目了解此示例和代码,但是对于我较差的动画技巧来说,从该示例过渡到具有时间意识的路径是很困难的。

Thanks 谢谢

Guido 圭多

A Bézier curve has not only a start and end point but also control points that guide the shape of the curve. 贝塞尔曲线不仅具有起点和终点,而且还具有控制曲线形状的控制点 In the DynApi demo you linked, the end points are marked in yellow, and the control points are marked in red. 在您链接的DynApi演示中,端点标记为黄色,控制点标记为红色。

Your path will be a sequence of Bézier curves, connected end-to-end. 您的路径将是一系列Bézier曲线,这些曲线首尾相连。

So let's take your pseudocode, but we'll treat all points that do not have a .time property to be control points. 因此,让我们使用您的伪代码,但是我们会将所有没有 .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;
}

So that's the math part done. 这就是数学部分。 It's up to you to hook it up to canvas and make it go. 由您决定将其连接到画布上并使其移动。

Here's how you call that method: 这是您调用该方法的方式:

// 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);

The control points of a bezier curve are in fact exactly what you get by adding the desired velocity vector at each end point to the end point. 贝塞尔曲线的控制点实际上就是您通过将每个端点处的所需速度矢量添加到端点而得到的。 For example, if you want velocity vx0,vy0 at point x0,y0 and then to proceed to point x1,y1 arriving there with velocity vx1,vy1, then use the following four points to define your bezier curve: (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1) 例如,如果您要在点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) . (x0,y0); (x0+vx0,y0+vy0); (x1-vx1,y1-vy1); (x1,y1) (the middle two are your control points.) (中间两个是您的控制点。)

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

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