Canvas 绘制图像的三种方法、实现帧动画

绘制图像与帧动画
本文介绍了使用Canvas API绘制图像的三种方法,并通过实例演示了如何实现帧动画效果,包括图像剪切、坐标定位及动态更新。
绘制图像的三种方法

/*
* 绘制图像
* ctx.drawImage();
*/
//第一种版本 三参数版本context.drawImage(img,x,y);,把图形绘制到指定的坐标
//必须要在图片下载之后才可以使用,使用onload事件
img.οnlοad=function(){
ctx.drawImage(img,10,10);
}
//第二种版本 五参数版本context.drawImage(img,x,y,width,height); 把图形绘制到指定的坐标、设置图像的宽高
//必须要在图片下载之后才可以使用
img.οnlοad=function(){
ctx.drawImage(img,10,10,200,200);
}
//第三种版本 九参数版本 context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
sx :开始剪切的X坐标,sy:开始剪切的Y坐标,swidth:被剪切图像的宽度,sheight:被剪切图像的高度
//必须要在图片下载之后才可以使用
img.οnlοad=function(){
ctx.drawImage(img,
100,100,200,300,
10,10,200,200);
}

实现帧动画







canvas{
border: 1px solid salmon;
}
img{
width:300px;
height: 300px;
display: none;
}

</head>
<body>
    <canvas id="cvs" width="500" height="500"></canvas>
    <img src="../img/NPC4.png"/>
    <script src="../js/Person.js" type="text/javascript" charset="utf-8"></script>
   <script>
     var cvs = document.getElementById('cvs');
    var ctx = cvs.getContext('2d');
    var img = document.querySelector('img');

      // 必须要在图片加载完毕之后,才能使用
    img.onload = function() {
        var person = new Person( ctx, img, 4, 4, 150, 150, 150, 150 );
        person._bind();

        // 修改direction,那么就是修改小人的行走方向
        person.direction = 2;

        setInterval( function() {

            // 清除画布
            ctx.clearRect( 0, 0, cvs.width, cvs.height );

            // 绘制
            person.draw();
            person.currentFrame = ++person.currentFrame >= person.widthFrame? 0 : person.currentFrame;

            // 计算下一次绘制时,小人的位置
            person.update();

        }, 100);
    }

</script>


</body>


js代码

(function( w ) {

// 混入式继承( copy继承 )
function extend( o1, o2 ) {
    for ( var key in o2 ) {
        if ( o2.hasOwnProperty( key ) ) {
            o1[ key ] = o2[ key ];
        }
    }
}

/*
 * constructor { Person } 人构造函数
 * param { ctx: Context } 绘制环境
 * param { img: Image } 绘制的图像
 * param { widthFrame: number } 图像一排有多少个人
 * param { heightFrame: number } 图像一列有多少个人
 * param { x: number } 指定人物绘制的x轴坐标
 * param { y: number } 指定人物绘制的y轴坐标
 * param { renderWidth: number } 人物绘制时的宽
 * param { renderHeight: number } 人物绘制时的高
 * param { speed: number } 人物行走的速度
 * */
function Person( ctx, img, widthFrame, heightFrame, x, y, renderWidth, renderHeight, speed ) {

    this.ctx = ctx;
    this.img = img;
    this.widthFrame = widthFrame;
    this.heightFrame = heightFrame;

    // 图像绘制时的坐标和大小
    this.x = x;
    this.y = y;
    this.renderWidth = renderWidth;
    this.renderHeight = renderHeight;

    // 行走的速度
    this.speed = speed || 2;

    // 求一个人的宽和高
    this.width = this.img.width / this.widthFrame;
    this.height = this.img.height / this.heightFrame;

    // 当前绘制某个方向的第几帧
    this.currentFrame = 0;

    // 当前行走的方向,默认是第一排的方向
    this.direction = 0;

    // 绑定事件
    this._bind();
}

// 给原型扩充方法
extend( Person.prototype, {

    // 绘制方法
    draw: function() {

        this.ctx.drawImage( this.img,
            this.width * this.currentFrame, this.height * this.direction, this.width, this.height,
            this.x, this.y, this.renderWidth, this.renderHeight);

    },

    // 绑定事件
    _bind: function() {

        var self = this;

        document.addEventListener( 'keydown', function( e ) {

            // 根据按键切换行走方向
            switch ( e.keyCode ) {
                case 37:
                    self.direction = 1;
                    break;
                case 38:
                    self.direction = 3;
                    break;
                case 39:
                    self.direction = 2;
                    break;
                case 40:
                    self.direction = 0;
                    break;
            }

        } );
    },

    // 更新小人下一阵绘制时的数据
    update: function() {

        switch ( this.direction ) {

            // 向下走,y轴加
            // 当小人向下出画布,那么从上边再走出来
            case 0:
                this.y += this.speed;
                this.y = this.y > this.ctx.canvas.height? -this.height: this.y;
                break;

            // 向左走,x轴减
            // 当小人向左走出画布,那么从右边再走出来
            case 1:
                this.x -= this.speed;
                this.x = this.x < -this.width? this.ctx.canvas.width: this.x;
                break;

            // 向右走,x轴加
            // 当小人向右走出画布,那么从左边再走出来
            case 2:
                this.x += this.speed;
                this.x = this.x > this.ctx.canvas.width? -this.width: this.x;
                break;

            // 向上走,y轴减
            // 当小人向上出画布,那么从下边再走出来
            case 3:
                this.y -= this.speed;
                this.y = this.y < -this.height? this.ctx.canvas.height: this.y;
                break;
        }

    }

} );

// 对外暴露Person
w.Person = Person;

}( window ));

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值