美文网首页
canvas多个元素的动画

canvas多个元素的动画

作者: 英俊又可爱XD | 来源:发表于2018-01-17 15:18 被阅读0次

    多个图片元素的动画绘制

    步骤:
    1. 每一帧动画的元素都重新绘制在画板中;
    2. 将元素创建的对象放入数组中,遍历元素,图片加载onload后绘制;
    var imgArr=[obj1, obj2 …];     //对象数组
    var count = 0;      //遍历对象的计数器
    imgArr.forEach( function(img){
    count++;    //计数器计数
    if (count == imgArr.length) {  //imgArr中所有元素加载完毕
    function draw( ){
     绘制每一帧的动作;    //tips: 重置画布画纸、画各个元素、递归
    window.requestAnimationFrame(draw);  //递归:自适应帧率
    }
    draw();    //第一次调用:推一下,跑起来~
    }
    })
    
    1. 将每个元素的绘制都封装在函数draw中,在draw中写递归(draw外手动调用);
    2. draw函数开始需要进行重置:清空画布、换纸
    3. 每个图片、文字或图形的绘制参数可以进行封装;
    4. 画布进行位移/旋转前进行context的读档和存档,换纸。

    案例:地球围绕太阳转

    实现效果:


    地球绕着太阳转.gif
    步骤:
    1. 创建图片对象并添加到数组,forEach遍历数组,加载图片
    2. 图片加载后执行函数draw,每次执行draw都会把太阳图片和地球图片重新drawImage一次
    太阳与地球分析.jpg

    代码如下:

    <body><canvas height="400" width="600" id="canvas"></canvas></body>
    <script>
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d");
        var earth = new Image();     //创建元素的对象和数组
        var sun = new Image();
        sun.src = "./img/Canvas_sun.png";
        earth.src = "./img/Canvas_earth.png";
        var imgArr = [sun, earth]; 
        var count = 0;
        imgArr.forEach(function (img) {     //forEach遍历
            img.onload = function () {
                count++;
                if (count == imgArr.length) {
                    function draw(){     //函数draw
                    context.save();     //清画板,存档画笔状态
                    // context.beginPath();
                    context.drawImage(sun, 0, 0);     //画太阳
                    var now = new Date();     //算草稿纸角度:秒和千秒
                    var seconds = now.getSeconds() + now.getMilliseconds()/1000 ;
                    var earthR = seconds/30*Math.PI;
                    var earthX = sun.width/2 - earth.width;     //算地球xy
                    var earthY = -earth.height/2;
                    context.translate(sun.width/2, sun.height/2);     //挪纸,转角度
                    context.rotate(earthR);
                    context.drawImage(earth, earthX, earthY);     //画地球
                    context.restore();     //读档画笔状态(重置状态)
                    window.requestAnimationFrame(draw);     //自适应帧率动画,回调draw
                    }
                    draw();     //第一次调用
                }
            }
        })
    </script>
    

    案例:机械时钟的绘制

    呈现效果:


    机械钟.gif
    思路:

    1.每一帧都重新绘制所有元素,包括表盘和指针。
    2.时刻线、指针均用草稿纸旋转完成,每一根指针的绘制都需要重新读档存档。
    3.每一帧开始前都需要保证画板的坐标处于原始状态。


    时钟在画布上的角度分析.png

    代码实现:

    <body>
    <canvas width="600" height="400" id="canvas" style = "border:1px solid #555"></canvas></body>
    </html>
    <script>
        var canvas= document.getElementById("canvas");
        var context = canvas.getContext("2d");
        function draw(){     //draw函数
            context.clearRect(0,0,600,400);     //初始化
            context.beginPath();
        //画表盘
            context.strokeStyle="seagreen";
            context.lineWidth = 4;
            context.arc(300,200,140,0,2*Math.PI);     //画圆
            context.stroke();
            context.beginPath();    //新纸
            //存档ct
            context.save();   //存档1:坐标系0, 笔粗4
            //循环:转稿纸画线
                context.translate(300,200); //坐标系300-200, 笔粗4
            for(var i =0; i<12; i++){
                context.rotate(Math.PI/6);
                context.moveTo(125,0);
                context.lineTo(135,0);
            }
            context.stroke();
            context.beginPath();  //新纸
                context.lineWidth = 2;   //坐标系300-200 笔粗2
            for(var i =0; i<60; i++){
                context.rotate(Math.PI/30);
                context.moveTo(130,0); 
                context.lineTo(135,0);
            }
            context.stroke();     //印制,新纸
            context.beginPath();
        //画时针
            var now = new Date();     //获取时间,算角度
            var hourR =now.getHours()>12?(now.getHours()-12)*Math.PI/6 : (now.getHours())*Math.PI/6;
            //读档,位移,旋转,印制,新纸
            context.restore();  //读存档1:坐标系0, 笔粗4
            context.save();      //存档1:坐标系0, 笔粗4
            context.translate(300,200);    //坐标系300-200, 笔粗4
            context.rotate(-Math.PI/2);    //坐标系300-200,-90° 笔粗4
            context.lineWidth=8;     //坐标系300-200,-90° 笔粗8
            context.lineCap="round";
            context.save();   //存档2:坐标系300-200,-90° 笔粗8
            context.rotate(hourR); 
            context.moveTo(-10,0);
            context.lineTo(50,0);
            context.stroke();
            context.beginPath();  //新纸
        //画分针
            var minuteR = now.getMinutes()/30*Math.PI; //算角度
            // console.log(minuteR);
            //读档,位移,旋转,印制,新纸
            context.restore();   //读存档2:坐标系300-200,-90°
            context.save();  //存档2
            context.rotate(minuteR);
            context.moveTo(-15,0);
            context.lineTo(95,0);
            context.lineWidth = 6;
            context.stroke();
            context.beginPath();
        //画秒针
            var secondR = now.getSeconds()/30*Math.PI;   //算角度
            //读档,位移,旋转,印制
            context.restore();    //读存档2:坐标系300-200,-90°
            context.rotate(secondR);
            context.moveTo(-25,0);
            context.lineTo(115,0);
            context.lineWidth = 2;
            context.strokeStyle="#53C686";
            context.stroke();
        //画表芯:新纸,读档,印圆
            context.restore();    //读存档1:坐标系0, 笔粗4
            context.beginPath();
            context.fillStyle = "#53C686";
            context.arc(300,200,8,0,2*Math.PI);
            context.fill();
            window.requestAnimationFrame(draw); //自适应帧率,递归调用
        }
        draw();     //第一次draw
    </script>
    

    2018.1.17

    相关文章

      网友评论

          本文标题:canvas多个元素的动画

          本文链接:https://www.haomeiwen.com/subject/dzkuoxtx.html