HTML5 | Canvas中变量作用域与setInterval()方法的影响

Demo - 随机绘制圆环

实现思路:

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

实现方法:

  1. 定义画布和联系
  2. 设置步进属性
  3. 设置随机圆属性(5个参数:x,y,半径,开始,结束,方向)
  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一样得到不同的副本各自存值
  • Canvas的Context样式(strokeStyle/shadowColor/...)是针对该Canvas(画布)唯一的,即
  • 如果同时调用setInterval方法,则轮流执行,1,2,1,2,1,2...以此类推
  • 谨慎使用setInterval方法,同时运行多个会导致相互干扰

遗留问题:

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

时间: 2024-08-09 14:42:09

HTML5 | Canvas中变量作用域与setInterval()方法的影响的相关文章

HTML5 canvas 中的arcTo()方法的用法

除了arc()之外,Canvas的绘图环境对象还提供了另一个用于创建圆弧路径的方法,那就是arcTo().改方法接受了5个参数: arcTo(x1,x2,y1,y2,radius) arcTo()方法的参数分别代表两个点击圆形半径.该方法一指定的半径来绘制一条圆弧,此圆弧与当前点到第一个点(x1,y1)的连线相切,而且第一个点到第二点(x2,y2)的连线也相切.该方法的这些特性,使得它非常适合用了绘制矩形的原角. 使用arcTo()方法: html: <!Doctyp html> <ht

PHP和JS中变量作用域

一,PHP中变量作用域 对于大多数PHP的变量只有一个作用域.在用户自定义函数里采用局部变量作用域.所有的函数内使用的变量被设置为局部变量.例如: <?php $a=1; function test() { echo $a; } test(); ?> 这段程序不会输出任何的东西因为echo语句要输出局部变量 $a ,而函数内的 $a 从未被赋过值.你可能注意到和C语言有点小小的区别,C中全局变量可以直接在函数内引用,除非它被一个局部变量所覆盖.因为这使得人们可能不注意修改了全局变量的值.在PH

php smarty模版引擎中变量操作符及使用方法

php smarty模版引擎中变量操作符及使用方法

HTML5 Canvas中的贝塞尔曲线

在HTML5提供的画布功能,也就是Canvas中,getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性.本文以getContext("2d")中提供的方法为例,简要研究了其中用于绘制曲线路径的贝塞尔曲线. JavaScript中的getContext("2d")为我们提供了两种绘制贝塞尔曲线路径的方法,分别是quadraticCurveTo()用于绘制二次贝塞尔曲线和bezierCurveTo()用于绘制三次贝塞尔曲线. 什么是贝塞

erlang中变量作用域

http://erlangdisplay.iteye.com/blog/315452 erlang中变量只能一次赋值,这么“苛刻“的要求下,更别想拥有全局变量了. 变量只在function中存在,这就是函数编程语言的特色. 对于函数参数对应的变量从执行函数开始,到函数执行结束(从咱们编程者的角度来看的确如此,至于从运行时,GC的角度看,咱们就不深究了). 比如下面的函数: Erlang代码   test1(V) -> io:format("V is:~p~n", [V]), % 

强制性输出private中变量的三种方法

众所周知,private里面的变量不可以输出,但是也可以通过特殊途径获得. 1.通过指针暴力内存,把它索罗出来,方法:调试,破掉语法. 并且还可以对类对象进行修改. 1 // Thread.cpp : 定义控制台应用程序的入口点. 2 // 3 4 #include "stdafx.h" 5 #include <WinSock2.h> 6 #include <Windows.h> 7 8 #include <iostream> 9 using nam

canvas中的rotate的使用方法

今天在绘制一个足球滚动的时候,想使用rotate方法,之前看到这个方法的时候,并没有引起任何重视,无非就是和CSS3里的rotate一样的用么... 遗憾的是,事实并非如此,由于代码在公司,我也就不去找那些图片资源了,直接用一个黑色方块代替 代码如下: var oCan = document.getElementById("canvas"); var ctx = oCan.getContext("2d"); ctx.rotate(30 * Math.PI / 180

Javascript中变量作用域

1 <script type="text/javascript"> 2 var a = 10; 3 4 var Bar = (function () { 5 console.log(a); //undefine 6 var a = 20; 7 return function () { a += 1; console.log(a); }; 8 })(); 9 Bar(); 10 Bar(); 11 </script> 看上面一段代码,当声明全局变量a后,在函数表达

vba中变量作用域

参考:http://club.excelhome.net/thread-1237085-1-1.html 全局变量例子public 变量1 AS IntegerSub LLL()变量1 = 1111End Sub 模块级变量例子DIM 变量1 AS IntegerSub LLL()变量1 = 1111End Sub 参考:http://www.excelpx.com/thread-334103-1-1.html 我有a.b.c三个宏模块,每个里面都有一个变量 dim sj as date, 这三