一次canvas动画的大笔试

栏目: 后端 · 发布时间: 4年前

内容简介:这是一道笔试题,要求是这么说的 定义了多组坐标数据,要实现坐标之间的连线动画(不考虑曲线),以及暂停与播放功能,还有重置,这可太难了呀,还不让依赖工具,于是我就放弃了。放弃不可能,还是试一下吧!html css js 用div做.....怎么做呢...我艹,算了,换canvas吧,还是canvas爽一点。 那么我特么为什么要用canvas呢

这是一道笔试题,要求是这么说的 定义了多组坐标数据,要实现坐标之间的连线动画(不考虑曲线),以及暂停与播放功能,还有重置,这可太难了呀,还不让依赖工具,于是我就放弃了。

放弃不可能,还是试一下吧!

技术选型

html css js 用div做.....怎么做呢...我艹,算了,换canvas吧,还是canvas爽一点。 那么我特么为什么要用canvas呢

  1. 绘制点到点的动画,多是利用插值技术,也不排除一些骚操作
  2. canvas绘制之后不清除是会一直存留的,不必在插值的路径上去创建像素
  3. canvas对交互动画有着一定的天然优势,如果人家非要让我用div或者svg,那我也只要自闭了

创建依赖

依赖总是我最喜欢写的东西,2D总是离不开Vector2,开始构建我们可爱的VV

var Vector = function(x = 0,y = 0) {
    this.x = x;
    this.y = y;
}
复制代码

然后稍微加工一下

Vector.prototype={
    add:function(v){
        return new Vector(this.x+v.x,this.y+v.y);
    },
    subtract:function(v){
        return new Vector(v.x-this.x,v.y-this.y);
    },
    length:function(){
        return Math.sqrt(this.x*this.x+this.y*this.y);
    },
    divide:function(n){
        return new Vector(this.x/n,this.y/n);
    },
    unit:function(){
        return this.divide(this.length());
    },
    lerp:function(v){
        let dirV = this.subtract(v);
        let unit = dirV.unit();
        return this.add(unit);

    }
}
复制代码

如此一来,基本的核心功能就出来了

BALL的构建

至于为什么叫BALL,也许是因为热衷于球吧。

var ball = function(x = 0,y = 0 ){
    this.x = x;
    this.y = y;
    this.status = MOVEING;

}
ball.prototype.render = function(context){
    let self = this;
    context.save();
    context.fillStyle = fillStyle;
    context.rect(self.x, self.y,5,5);
    context.fill();
    context.restore();
}
ball.prototype.lerp = function(site){
    //插值计算,不断更新坐标
    let self = this;
    let dirV = new Vector(...site);
    self.site = new Vector(this.x,this.y);
    let n_site = self.site.lerp(dirV);
    self.x = n_site.x;
    self.y = n_site.y;
}
复制代码

正如你所见,利用了向量的插值计算来不断更新当前坐标来实现超速移动。 使用 status 来处理不同状态的BALL,善于使用状态量会使代码逻辑更加舒适,这里定义了所需要的状态

const PEDDING = 'PEDDING';
const MOVEING = 'MOVING';
const RESETING ='RESETING';
复制代码

主逻辑

整体的主要逻辑就是不断对BALL进行插值更新,同时要处理小球的状态

function move(pos){
    context.clearRect(0, 0, can.width, can.height);
    a.render(context);
    switch (a.status) {
        case 'PEDDING':
            
            break;
        case 'MOVING':
            a.lerp(pos);
            break;
        // case 'RESETING':
        //     //小球RESETING状态,有BUG,可有可无
        //     a = null;
        //     context.clearRect(0, 0, can.width, can.height);
        //     a = new ball(...site[0]);
        //     index=0;
        //     //a.status = MOVEING;          
        //     break;
        default:
            break;
    }
}
复制代码

不要太在意那个BUG,程序员的BUG能叫BUG吗?

渲染部分

function run(){
    let x = site[index+1][0];
    let y = site[index+1][1];
    console.log(index)
    if(a.x>=x-1&&a.y>=y-1){
        index=index+1;
    }
    if(site[index+1]){
        move(site[index+1]);
        requestAnimationFrame(run)
    }
    if(a.status==RESETING){
        context.clearRect(0, 0,2000,1000);
        //这里弃用
    }
}
(function(){
    site.length>=2?requestAnimationFrame(run):' ';
})()
复制代码

这里只需要注意坐标序列的长度,避免只有一个坐标,还有就是当前索引归属于下一个索引的存在与否。

这里是个小TIP,不要再动画的循环中写过多的逻辑,能封装出去的逻辑尽量封装出去,不然会显得代码异常臃肿。

交互部分

<button onclick="pause()">暂停</button>
    <button onclick="play()">播放</button>  
    <button onclick="reset()">重置</button>   
复制代码
//重置 暂停 运行
function reset(){  
    location.reload();
    //a.status = RESETING;
}
function pause(){
    a.status = PEDDING;
}
function play(){
    a.status = MOVEING;
}
复制代码

由于canvas的clearRect有点问题,效果一直出不来,这里直接采用强行F5的安全措施,保证安全。

效果也算是完成了,其实还可以有很多拓展的部分,比如曲线连接,回放效果等,不知道你有啥骚操作呢,come on !


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

游戏化实战

游戏化实战

[美]Yu-kai Chou / 杨国庆 / 华中科技大学出版社 / 2017-1 / 59.00

TED演讲人作品,罗辑思维、华为首席用户体验架构师、思科网络体验CTO推荐。 随书附有TED演讲中文视频及作者开设的游戏化初学者课程。作者为Google、乐高、华为、思科、斯坦福大学、丹麦创新中心等多家企业、机构提供高层培训与合作。 ********************** “我长期以来都在密切关注Yu-kai的研究成果。任何想要让工作、生活变美好的人都应该阅读这本书。” ......一起来看看 《游戏化实战》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器