html5画布-沿路径设置对象动画

html5画布-沿路径设置对象动画,html,animation,html5-canvas,raphael,Html,Animation,Html5 Canvas,Raphael,我对画布有点陌生,所以如果这是一个琐碎的问题,请原谅 我希望能够按照路径(定义为bezier路径)为对象设置动画,但我不确定如何做到这一点 我看过拉斐尔,但我不知道如何随着时间的推移走这条路 Cake JS在演示中看起来很有希望,但我真的很难找到文档,或者在本例中缺少文档 有人有这样的工作示例吗?除非你真的需要,否则我不会使用Canvas。SVG具有沿内置路径的动画。Canvas需要相当多的数学知识才能工作 以下是对拉斐尔的一些讨论: 请注意,Raphael使用SVG而不是HTML5画布 在

我对画布有点陌生,所以如果这是一个琐碎的问题,请原谅

我希望能够按照路径(定义为bezier路径)为对象设置动画,但我不确定如何做到这一点

我看过拉斐尔,但我不知道如何随着时间的推移走这条路

Cake JS在演示中看起来很有希望,但我真的很难找到文档,或者在本例中缺少文档


有人有这样的工作示例吗?

除非你真的需要,否则我不会使用Canvas。SVG具有沿内置路径的动画。Canvas需要相当多的数学知识才能工作

以下是对拉斐尔的一些讨论:

请注意,Raphael使用SVG而不是HTML5画布


在画布中沿贝塞尔路径设置动画的一种方法是连续对分贝塞尔曲线,重新记录中点,直到有许多点(例如,每条曲线50个点)可以沿该点列表设置对象动画。搜索对分beziers和类似的查询,以获取相关的数学信息。

使用中的代码,但不要更改
.style.left
以及回调中的类似内容,擦除并在新位置重新绘制画布上的项目(以及可选的旋转)

请注意,这在内部使用SVG可以轻松地沿贝塞尔曲线插值点,但您可以使用它提供的点来实现任何目的(包括在画布上绘制)

如果我的站点关闭,以下是库的当前快照:

function CurveAnimator(from,to,c1,c2){
  this.path = document.createElementNS('http://www.w3.org/2000/svg','path');
  if (!c1) c1 = from;
  if (!c2) c2 = to;
  this.path.setAttribute('d','M'+from.join(',')+'C'+c1.join(',')+' '+c2.join(',')+' '+to.join(','));
  this.updatePath();
  CurveAnimator.lastCreated = this;
}
CurveAnimator.prototype.animate = function(duration,callback,delay){
  var curveAnim = this;
  // TODO: Use requestAnimationFrame if a delay isn't passed
  if (!delay) delay = 1/40;
  clearInterval(curveAnim.animTimer);
  var startTime = new Date;
  curveAnim.animTimer = setInterval(function(){
    var now = new Date;
    var elapsed = (now-startTime)/1000;
    var percent = elapsed/duration;
    if (percent>=1){
      percent = 1;
      clearInterval(curveAnim.animTimer);
    }
    var p1 = curveAnim.pointAt(percent-0.01),
        p2 = curveAnim.pointAt(percent+0.01);
    callback(curveAnim.pointAt(percent),Math.atan2(p2.y-p1.y,p2.x-p1.x)*180/Math.PI);
  },delay*1000);
};
CurveAnimator.prototype.stop = function(){
  clearInterval(this.animTimer);
};
CurveAnimator.prototype.pointAt = function(percent){
  return this.path.getPointAtLength(this.len*percent);
};
CurveAnimator.prototype.updatePath = function(){
  this.len = this.path.getTotalLength();
};
CurveAnimator.prototype.setStart = function(x,y){
  var M = this.path.pathSegList.getItem(0);
  M.x = x; M.y = y;
  this.updatePath();
  return this;
};
CurveAnimator.prototype.setEnd = function(x,y){
  var C = this.path.pathSegList.getItem(1);
  C.x = x; C.y = y;
  this.updatePath();
  return this;
};
CurveAnimator.prototype.setStartDirection = function(x,y){
  var C = this.path.pathSegList.getItem(1);
  C.x1 = x; C.y1 = y;
  this.updatePath();
  return this;
};
CurveAnimator.prototype.setEndDirection = function(x,y){
  var C = this.path.pathSegList.getItem(1);
  C.x2 = x; C.y2 = y;
  this.updatePath();
  return this;
};
…以下是您可以如何使用它:

var ctx = document.querySelector('canvas').getContext('2d');
ctx.fillStyle = 'red';

var curve = new CurveAnimator([50, 300], [350, 300], [445, 39], [1, 106]);

curve.animate(5, function(point, angle) {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.fillRect(point.x-10, point.y-10, 20, 20);
});​

实际上:

所以,下面是详细的版本:

t
是0到1之间表示时间的任意数字;
p0
p1
p2
p3
对象分别为起点点、第一控制点点、第二控制点点和终点

var at = 1 - t;
var green1x = p0.x * t + p1.x * at;
var green1y = p0.y * t + p1.y * at;
var green2x = p1.x * t + p2.x * at;
var green2y = p1.y * t + p2.y * at;
var green3x = p2.x * t + p3.x * at;
var green3y = p2.y * t + p3.y * at;
var blue1x = green1x * t + green2x * at;
var blue1y = green1y * t + green2y * at;
var blue2x = green2x * t + green3x * at;
var blue2y = green2y * t + green3y * at;
var finalx = blue1x * t + blue2x * at;
var finaly = blue1y * t + blue2y * at;
这是一个

变量名称来自此gif,这是贝塞尔曲线的最佳解释:

代码的简短版本,位于准备复制/粘贴的函数内:

var calcBezierPoint = function (t, p0, p1, p2, p3) {
    var data = [p0, p1, p2, p3];
    var at = 1 - t;
    for (var i = 1; i < data.length; i++) {
        for (var k = 0; k < data.length - i; k++) {
            data[k] = {
                x: data[k].x * at + data[k + 1].x * t,
                y: data[k].y * at + data[k + 1].y * t
            };
        }
    }
    return data[0];
};
var calcBezierPoint=函数(t,p0,p1,p2,p3){
var数据=[p0,p1,p2,p3];
var at=1-t;
对于(变量i=1;i


相关资料:


感谢您的意见。。我发现的大多数svg动画示例看起来。。。任何svg路径都可以使用的笨重东西。。。只需将this.path.setAttribute更改为具有给定路径的init即可。@Ben当然可以。:)你可能对……感兴趣。@Phrogz。Gavin,试图通过电子邮件向您发送有关代码许可证的信息![在]phrogz.net,但它不断通过未经授权的中继反弹。还有其他地址可以联系你吗?@Ben myfirstname在Samedomain我对数学也不太了解;但是你可以在谷歌上搜索并意识到,对于这样一个简单的问题,这个解决方案是荒谬的,特别是如果你使用的是画布。检查下面我的答案中的数学。谢谢你的迟交。但没必要这么傲慢@phrogz的答案非常棒,在任何道路上都有效;它使用一个专有的库,单个用户有太多的代码,它使用的SVG速度较慢,在Android和其他设备上不受支持这也适用于任何路径;只需更改p0、p1、p2和p3的值。如果你需要帮助获得正确的号码,你可以使用“相关资料”中的第一个链接。我们需要免费帮助,我们需要谦虚地去做吗?告诉我我们需要做的一切。感谢您提供了这个非常好的解决方案和示例!如果你把第一句话改成“这是一个备选答案”,我会给你的答案a+1。