欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Canvas 帧动画(封装成对象),绘制图片(drawImage())

程序员文章站 2022-03-21 13:50:59
...


person.js(封装的外部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 || 5;

        // 求一个人的宽和高
        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 ));


demo.html(利用person.js实现帧动画):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        canvas {
            border:1px solid red;
        }
        img {
            display: none;  /* 隐藏img标签,让图像在canvas画布上显示 */
        }
    </style>
</head>
<body>
    <canvas id="cvs" width="500" height="500"></canvas>
    <img src="./imgs/NPC5.png">
    <script src="person.js"></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, 50, 50, 50, 50 );

            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>
</html>

imgs/NPC.png:

Canvas 帧动画(封装成对象),绘制图片(drawImage())