canvas实现基本动画

基本步骤:

1.清空canvas,最简单的方法是使用clearRect()方法清空画布

2.保存canvas状态。如果要改变canvas设置状态,如样式、变形等,又要在每画一帧之时都要重设原始状态,这时需要save方法先保存canvas设置状态

3.绘制动画图形

4.恢复canvas状态,如果已经保存了canvas状态,可以使用restore方法先恢复它,然后重绘下一帧

实现动画操作方法:

        setTinterval( function, delay ):定时器

        setTimeout( function, delay ):延时器

        requestAnimationFrame( callback ):告诉浏览器希望执行动画,并请求浏览器调用指定的callback函数在下一次重绘之前更新动画。该函数不需要指定动画关键帧间隔的时间,浏览器自动设置

例一:动态展示不同图形合成效果

<script>
    var globalId, i=0;
    function draw(id){
        globalId = id;
        setInterval(Composite, 1000);
    };
    function Composite(){
        var canvas = document.getElementById("myCanvas");
        if(canvas === null) return false;
        var ctx = canvas.getContext("2d");
        var oprtns = new Array("source-over", "source-in", "source-out", "source-atop", "destination-over", "destination-in", "destination-out", "destination-atop", "lighter", "copy", "xor");
        if(i>10) i=0;
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.save();
        ctx.font = "30px Georgia";
        ctx.fillText("合成方案: "+oprtns[i], 240, 130);
        //绘制原有图形(蓝色长方形)
        ctx.fillStyle = "blue";
        ctx.fillRect(0,0,100,100);
        //设置组合方式
        ctx.globalCompositeOperation = oprtns[i];
        //设置新图形(红色圆形)
        ctx.fillStyle = "red";
        ctx.arc(100,100,100,0,Math.PI*2,false);
        ctx.fill();
        ctx.restore();
        i++;
    };
    draw("myCanvas");
</script>

例二:运动拖尾效果

<script>
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    var ball = {
        x:100,
        y:100,
        vx:5,
        vy:5,
        radius: 25,
        color: 'blue',
        draw: function(){
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
            ctx.fillStyle = this.color;
            ctx.fill();
        }
    }
    ball.draw();
    //添加速率,使用window.requestAnimationFrame()控制动画,通过递增速率矢量移动小球,在每一帧里面(draw函数)重绘小球,先使用clearRect()清除画布,再绘制小球
    function draw(){
        //设计边界,若没有任何碰撞检测,小球很快就会超出画布,检查是否需要将速率矢量反转
        if(ball.x + ball.vx + ball.radius > canvas.width || ball.x + ball.vx - ball.radius < 0){
            ball.vx = - ball.vx;
        }
        if(ball.y + ball.vy + ball.radius > canvas.height || ball.y + ball.vy - ball.radius < 0){
            ball.vy = - ball.vy;
        }
        // ctx.clearRect(0,0,canvas.width,canvas.height); 使用半透明fillRect()可以避免重绘且制作长尾效果
        ctx.fillStyle = "rgba(255,255,255,0.3)";
        ctx.fillRect(0,0,canvas.width,canvas.height);
        
        ball.draw();
        ball.x += ball.vx;
        ball.y += ball.vy;
        //设计弹跳动画,逐帧减少垂直方向速度,小球最终只会在地板上弹跳
        ball.vy *= 0.99
        ball.vy += 0.25
        raf = window.requestAnimationFrame(draw);
    }
    canvas.addEventListener("mouseover", function(e){
        raf = window.requestAnimationFrame(draw);
    })
    canvas.addEventListener("mouseout", function(e){
        window.cancelAnimationFrame(raf);
    })
    
</script>