会爬行的蜘蛛canvas

所属分类:其他-动画效果

 37529  456  查看评论 (33)
分享到微信朋友圈
X
会爬行的蜘蛛canvas ie兼容11

verlet.js 运动算法详解


本系列文章可以在这里查看:verletjs动画框架

你可以从这里查看该项目的所有源文件:

涉及文件:lib/vec2.js


构造函数

function Vec2(x, y) {
 this.x = x || 0;
 this.y = y || 0;
}

该函数定义了空间中(二维)的一点,对应canvas的坐标性质(左上角为坐标原点)


向量


正如高中数学所学,verletjs的动画都是基于向量实现的,向量顾名思义:有大小,有方向,这里的方向就是x,y两个方向。动画中涉及的任何一个“量”都可以看成一个向量。如:速度、重力、摩擦力等等。


向量加法

Vec2.prototype.add = function(v) {
    return new Vec2(this.x + v.x, this.y + v.y);
}

如果一个向量A[1,2],另一个向量B[3,4];那么向量A+B=[1+3,2+4]=[4,6]


注意:以下的几个方法都是返回一个新对象。


向量减法

Vec2.prototype.sub = function(v) {
    return new Vec2(this.x - v.x, this.y - v.y);
}


向量乘法

Vec2.prototype.mul = function(v) {
    return new Vec2(this.x * v.x, this.y * v.y);
}


向量除法

Vec2.prototype.div = function(v) {
     return new Vec2(this.x / v.x, this.y / v.y);
}


缩放

Vec2.prototype.scale = function(coef) {
    return new Vec2(this.x*coef, this.y*coef);
}

其实缩放可以看成乘法,也可以看成除法;因为都能通过以上两种方法来实现。


位置重置

Vec2.prototype.mutableSet = function(v) {
    this.x = v.x;
    this.y = v.y;
    return this;
}


向量是否相等

Vec2.prototype.equals = function(v) {
    return this.x == v.x && this.y == v.y;
}


向量的长度(模)

Vec2.prototype.length = function(v) {
    return Math.sqrt(this.x*this.x + this.y*this.y);
}

可以这么理解,速度是有大小,有方向的。但是当我们需要用速度大小进行计算的时候就需要用到速度的模了。


两点间的距离(标量)

Vec2.prototype.dist2 = function(v) {
     var x = v.x - this.x;
     var y = v.y - this.y;
    return x*x + y*y;
}
Vec2.prototype.dist = function(v) {
     return Math.sqrt(this.dist2(v));
}


法向量

Vec2.prototype.normal = function() {
    var m = Math.sqrt(this.x*this.x + this.y*this.y);
    return new Vec2(this.x/m, this.y/m);
}

所谓法向量就是和当前向量夹角为90度的向量;可以理解为:物体的重力和受到地面的反作用力。


向量点积

Vec2.prototype.dot = function(v) {
    return this.x*v.x + this.y*v.y;
}

向量的点积得到的结果是一个数字,并非是一个向量


两个向量之间的夹角

Vec2.prototype.angle = function(v) {
     return Math.atan2(this.x*v.y-this.y*v.x,this.x*v.x+this.y*v.y);
}
 
Vec2.prototype.angle2 = function(vLeft, vRight) {
    return vLeft.sub(this).angle(vRight.sub(this));
}


向量旋转

Vec2.prototype.rotate = function(origin, theta) {
    var x = this.x - origin.x;
    var y = this.y - origin.y;
    return new Vec2(x*Math.cos(theta) - y*Math.sin(theta) + origin.x, x*Math.sin(theta) + y*Math.cos(theta) + origin.y);
}

这个旋转是基于某个位置,某个角度进行的旋转。旋转后得到一个新的向量;旋转的用处很大,比如有些时候根据鼠标的移动展现不同角度的动画。旋转在3D动画开发中尤其重要,接下来补充几个3D旋转算法: 

/*
* 绕X轴旋转
* @param {Number} angle 旋转的角度(弧度)
*/
Vector3D.prototype.rotateX: function(angle) {
     var ca = Math.cos(angle);
     var sa = Math.sin(angle);
 
     var tmpY = this.y * ca - this.z * sa;
     var tmpZ = this.y * sa + this.z * ca;
 
     this.y = tmpY;
     this.z = tmpZ;
}
 /*
  * 绕Y轴旋转
  * @param {Number} angle 旋转的角度(弧度)
  */
Vector3D.prototype.rotateY: function(angle) {
     var ca = Math.cos(angle);
     var sa = Math.sin(angle);
     with(this) {
         var tmpX = x * ca + z * sa;
         var tmpZ = x * -sa + z * ca;
         x = tmpX;
         z = tmpZ;
     }
}

实际应用中并不推荐使用with语句,其实with语句的目的就是改变当前语句块的执行环境;即把this注入到语句块中,省去每次都要写this的麻烦。

/*
* 绕Z轴旋转
* @param {Number} angle 旋转的角度(弧度)
*/
Vector3D.prototype.rotateZ: function(angle) {
     var ca = Math.cos(angle);
     var sa = Math.sin(angle);
     var tmpX = this.x * ca - this.y * sa;
     var tmpY = this.x * sa + this.y * ca;
     this.x = tmpX;
     this.y = tmpY;
}
/*
* 绕XY轴旋转
* @param {Number} a 旋转的角度(弧度)
* @param {Number} b 旋转的角度(弧度)
*/
Vector3D.prototype.rotateXY: function(a, b) {
     var ca = Math.cos(a);
     var sa = Math.sin(a);
     var cb = Math.cos(b);
     var sb = Math.sin(b);
 
     with(this) {
         // 绕x轴旋转
         var rz = y * sa + z * ca;
         y = y * ca - z * sa;
        // 绕y轴旋转
        z = x * -sb + rz * cb;
         x = x * cb + rz * sb;
     }
}
/*
* 绕XYZ轴旋转
* @param {Number} a 旋转的角度(弧度)
* @param {Number} b 旋转的角度(弧度)
* @param {Number} c 旋转的角度(弧度)
*/
Vector3D.prototype.rotateXYZ: function(a, b, c) {
     var ca = Math.cos(a);
     var sa = Math.sin(a);
     var cb = Math.cos(b);
     var sb = Math.sin(b);
     var cc = Math.cos(c);
     var sc = Math.sin(c);
 
     with(this) {
         // x
         var ry = y * ca - z * sa;
         var rz = y * sa + z * ca;
         // y
         var rx = x * cb + rz * sb;
         z = x * -sb + rz * cb;
        // z
         x = rx * cc - ry * sc;
         y = rx * sc + ry * cc;
     }
}


如何使用

动画中的一切和位置相关的计算都可以用向量来表示,这里以自由落体为例。


1、物体下落,有自身的重力、空气的阻力作用


2、假设物体从初速度为0开始下落


3、可以计算该物体下落的加速度


具体实现:

// 初速度
var vel = new Vec2(0, 0);
// 重力为10,方向垂直向下
var gravity = new Vec2(0, 10);
// 空气的阻力,大小为8,方向和重力相反
var f = new Vec2(0, 8);

// 计算物体所受合力
var all = gravity.sub(f); // (0, 2)
 
// 循环调用loop函数(可以理解为动画的一帧,循环播放。为一个时间单位)
var loop = function() {
     // 下一时刻的速度
     // 由于每帧为一个时间单位,也可以直接理解为下一时刻的位移
     // 然后在canvas中按照vel的位置重绘就得到了自由落体的效果
     vel.add(all);
     console.log(vel);
     window.requestAnimationFrame(loop);
 }
 loop();

接下来的几部分讲解verletjs是如何利用该动画原理来实现动画框架的。


相关插件-动画效果

3D云 (酷!)

3D云在云端!
  动画效果
 79645  1560

五种常用的Loading动效

基于jquery和css的简单五种Loading样式,易用,可扩展
  动画效果
 45685  315

jQuery css3手机页面转换动画特效

jQuery css3手机页面转换动画特效
  动画效果
 40256  452

jQuery浮层跟随图片动画代码

jQuery浮层跟随图片动画代码
  动画效果
 32889  387

讨论这个项目(33)回答他人问题或分享插件使用方法奖励jQ币 评论用户自律公约

    web前端-张超怡 0
    2018/1/26 14:01:47

    厉害了,收下我的膝盖吧, 我发现拽着蜘蛛的屁股,蜘蛛分尸了

    回复
    0
    2017/9/18 10:13:46

    揪着蜘蛛腿就出去了。。。

    回复
    小土龙/ka 0
    2017/7/4 11:58:24
    把蜘蛛甩出去了,,,,,
        平通0
        2017/8/23 10:51:50

        你是怎么甩出去的

        南笙??0
        2018/7/9 12:01:25
        蜘蛛确实可以甩出去 哈哈哈,我也甩出去了
        Seation0
        2018/9/3 17:14:16
        你们到底是来找插件的还是来玩的
    回复
    暮挽北城 0
    2017/6/16 11:37:51
    Dreamboy 0
    2017/5/22 16:17:41

    这效果,吊炸天啊

    回复
    草帽/aiq/oh小子 0
    2017/5/19 16:57:31
    ?╊Single° 0
    2017/1/6 10:01:51
    [!..!] 0
    2016/11/12 10:11:01
    yang609138440 0
    2016/10/20 16:10:43
    真尼玛厉害了
        圈圈0
        2016/10/20 16:10:07
        是作者编辑的用法  我只提供了插件
    回复
    zrsun 0
    2016/10/12 16:10:45
😃
  • 😀
  • 😉
  • 😥
  • 😵
  • 😫
  • 😘
  • 😡
  • 👍
  • 🌹
  • 👏
  • 🍺
  • 🍉
  • 🌙
  • 💖
  • 💔
😃
  • 😀
  • 😉
  • 😥
  • 😵
  • 😫
  • 😘
  • 😡
  • 👍
  • 🌹
  • 👏
  • 🍺
  • 🍉
  • 🌙
  • 💖
  • 💔
取消回复