H5 Canvas | 画布中变量作用域与setInterval方法同步执行探究

Demo - 随机绘制圆环

实现思路:

  • 将一个圆环的绘制分成100份,setInterval()方法定义每隔时间n绘制一段新的,每份的开始路径都是上一次的结束路径,实现步进绘制。
  • 通过Math.random(),随机生成圆的坐标半径颜色。

实现方法:

  1. 定义画布和联系
  2. 设置步进属性
  3. 设置随机圆属性(5个参数:xy,半径,开始,结束,方向)
  4. 循环执行绘画

<<index.html>>

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <style type="text/css">
    #canvas {
        border: 1px black solid;
    }
    </style>
</head>

<body>
    <canvas id="canvas" width="1000" height="400">您的浏览器不支持canvas</canvas>
    <input type="button" onclick="InitDraw()" value="draw">
    <script type="text/javascript">
    function InitDraw() {
        var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        var ctx2 = canvas.getContext('2d');

        var step;
        // var sAngle;
        // var eAngle;
        var x, y, r;
        var add, stepTime, counterClockwise;
        // 步进属性
        step = 0;
        add = Math.PI * 2 / 100;
        stepTime = 20;
        // 随机圆属性
        sAngle = 0;
        eAngle = sAngle + add;
        counterClockwise = false;
        x = Math.random() * 800 + 100;
        y = Math.random() * 200 + 100;
        r = Math.random() * 50 + 50;
        ctx.strokeStyle = "#" + (Math.random() * 0x1000000 << 0).toString(16);
        ctx.shadowColor = "#" + (Math.random() * 0x1000000 << 0).toString(16);
        console.log(ctx.strokeStyle);
        console.log(ctx2.strokeStyle);
        ctx.lineWidth = 1.0;
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
        ctx.shadowBlur = 10;

        // 画圆
        var drawID = setInterval(Draw, stepTime);

        function Draw() {
            if (step < 100) {
                // 绘制路径并画
                ctx.beginPath();
                ctx.arc(x, y, r, sAngle, eAngle, counterClockwise);
                ctx.stroke();
                ctx.closePath();
                // 步进
                sAngle = eAngle;
                eAngle += add;
                // console.log("drawID:" + drawID + ",step:" + step);
                // console.log(ctx.strokeStyle);
                step++;
            } else {
                clearInterval(drawID);
            }
        }

    }
    </script>
</body>

</html>

 

在不同的变量环境下出现了不同的情况:

  1. 全局变量:step, sAngle, eAngle , x, y, r;

    在执行绘图过程中持续变化的参数是step,sAngle,eAngle,再次调用时回到函数InitDraw();重新定义六个全局变量以及画笔样式,则重新开始绘图。上一个step和画笔样式都停留在按下button的一刻

  2. 全局变量:sAngle, eAngle; 局部变量:var step, x, y, r;

    在控制台输出情况可以看到,当起始位置为全局变量时相互干扰的非常厉害,但因为step是局部变量,调用的是不同的副本,最后两个圈均执行到了99。并且可以看到控制台中drawID是间隔出现的,对两次setInterval方法轮流执行,也就造成了sAngle位置是跳跃的虚点。

       

  3. 局部变量:var step ,sAngle, eAngle, x, y, r;

    但要注意的是在该示例中共用同一个画布和联系(ctx),在这里画笔的颜色和样式被刷新成为新的。那么应该如何在同一画布中同时绘画不同样式?

       

  4. 全局变量:step; 局部变量:var sAngle, eAngle, x, y, r;

    在第二次点击出现的圈绘到约半圈时停止

    点击button重新执行InitDraw();step=0; 从打印信息可以看到两个不同的setInterval方法对step变量相互干扰,直到step有机会到达99时停止绘图。

       

  5. ...一共64种变化,谨慎定义Canvas中的变量作用域

关于Context的另一个测试:

在同一个画布中调用获取两个Context,但通过输出可以看到每个画布只有一个对应的Context

   

经过几个Demo的分析得到以下结论:

  • 在调用同一个function时候,私有变量互不相干,会像C一样得到不同的副本各自存值
  • CanvasContext样式(strokeStyle/shadowColor/...)是针对该Canvas(画布)唯一的
  • 如果同时调用setInterval方法,则轮流执行,1,2,1,2,1,2...以此类推
  • 谨慎使用setInterval方法,同时运行多个会导致相互干扰

遗留问题:

  • 如何同时绘画不同样式?

posted @ 2017-07-25 20:31  hugh.dong  阅读(2345)  评论(0编辑  收藏  举报