1.6 HTML5 Canvas简介
HTML5 Canvas是屏幕上由JavaScript控制的即时模式位图区域。即时模式是指在画布上呈现像素的方式,HTML Canvas通过JavaScript调用Canvas API,在每一帧中完全重绘屏幕上的位图。开人员需要做的就是在每一帧渲染之前设置屏幕的内容显示。
1.6.1 文档对象模型和Canvas
文档对象模型(DOM)代表了HTML页面上的所有对象,它是语言中立且平台中立的。它允许页面的内容和样式被Web浏览器渲染之后再次更新。用户可以通过JavaScript访问DOM。现在DOM已经成为JavaScript、DHTML和CSS开发中最重要的一部分。
画布元素本身可以通过DOM在Web浏览器中经由Canvas 2D环境访问。但是,在Canvas中创建的单个图形元素是不能通过DOM来访问的。正如本章前面讲到的,画布工作在即时模式,它并不保存自己的对象,只是说明在单个帧里绘制什么。
❑ 在使用Canvas之前大家需要了解两个DOM对象,其中一个对象为document,它包含所有在HTML页面的HTML标签上。
❑ 另一个对象window是DOM的最高一级,需要检测这个对象来确保在开始使用Canvas应用程序之前,已经加载了所有的资源和代码。
1.6.2 JavaScript与Canvas
用JavaScript来创建Canvas应用程序,程序能在现有的任何Web浏览器中运行。在使用JavaScript为Canvas编程时会有一个问题,在创建的页面中哪里为JavaScript程序的起点?有两种方式,一种为放在<head>标签中,另一种为放在<body>标签中。
❑ 将起点放在<head>元素中意味着整个HTML页面要加载完JavaScript才能配合HTML运行,在运行该程序前就必须检查HTML页面是否已经加载完毕。
❑ 另一种将起点放在<body>元素内的好处是,它可确保JavaScript运行时整个页面已经加载完毕。由于在运行Canvas程序前需要使用JavaScript测试页面是否加载,所以两种方法各有利弊。本书在编写的时候用的是第二种,读者可以选择自己喜欢的方式进行编程。
1.6.3 HTML5 Canvas版“Hello World”
现在来开发Canvas之路上的第一个案例,即Canvas版的“Hello World”。本节将从开发程序的第一步开始,一步步地将程序开发的过程呈现给大家,让没有开发经验的读者对开发程序有一个整体的概念。
在上一节中讲到了JavaScript与Canvas的关系。由于在开发本部分内容时html文件中难免会嵌入JavaScript脚本,所以我们第一步来看一下如何将JavaScript程序中的方法封装起来,并留下JavaScript程序的入口。
1.封装JavaScript代码
Canvas应用程序与浏览器中运行的其他应用有所不同。由于Canvas只在屏幕上的特定区域内执行并显示结果,可以说它的功能是独占的,因此不太会受到页面上其他内容的影响,反之亦然。读者如果想在同一个页面上放置多个Canvas应用,那么在定义时必须将对应代码分开。
为了避免出现这个问题,可以将变量和函数都封装在另一个函数中。JavaScript函数本身就是对象,JavaScript对象既可以有属性也可以有方法。将一个函数放到另一个函数中,读者可以使第二个函数只在第一个函数的局部作用域中。
1 function eventWindowLoaded(){canvasApp(); } //JavaScript程序在Canvas中的入口函数 2 function canvasApp(){ //入口函数需要调用的函数 3 drawScreen(); //绘制场景函数 4 …… 5 function drawScreen(){…… //绘制函数,本程序中的重点 6 }}
上述代码讲解了如何将JavaScript代码封装起来,封装好的方法只留下eventWindowLoaded()方法。在下一节中还将绘制不同图形的方法并放到外部文件中,在<head>标签部分加载这些文件,待到需要绘制时直接调用相应的方法即可。
2.将Canvas添加到HTML页面中
在HTML的<body>标签中添加一个<Canvas>标签时,可以参考下述代码。<canvas>标签有3个主要属性。大家都知道在HTML中,属性被设置在相应的标签中,id、width、height这3个属性分别代表JavaScript代码中用来指示特定<canvas>标签的名字、画布的宽度与高度。
1 <canvas id="canvasOne" width="500" height="300"> 2 若看到这个文字,则说明浏览器不支持WebGL! </canvas>
在开始标签和结束标签中可以添加文本,一旦浏览器在执行HTML页面时不支持Canvas,就会显示这些文字。以本章的Canvas应用程序为例,这里使用的是“若看到这个文字,则说明浏览器不支持WebGL”。事实上此处可以随意放置文字。
接下来用DOM引用HTML中定义的<canvas>标签。document对象加载后可以引用HTML页面的任何元素。需要一个Canvas对象的引用,这样就能够知道当JavaScript调用Canvas API时其结果在哪里显示了。
var theCanvas=document.getElementById("canvasOne");
首先定义一个名为theCanvas的新变量,以保存Canvas对象的引用。接下来,通过调用document的getElementById()函数得到canvasOne的引用。canvasOne是在HTML页面中为创建的<canvas>标签定义的名字。
3.检测浏览器是否支持Canvas
现在已经得到了在HTML页面上定义的Canvas元素的引用,下面检测它是否包含环境。Canvas环境是指支持由Canvas的浏览器定义的绘图界面。简单地说,如果环境不存在,那么画布也不会存在。有多种方式可以对此进行验证。
这里使用的是modernizr.js库中的Modernizr,它是一个易用并且轻量级的库,可以检测各种Web技术的支持情况。Modernizr创建一组静态的布尔值,可以检测是否支持Canvas。在程序中已经包含modernizr.js,读者不用再自行下载了。
1 <script src="modernizr.js"></script> 2 function canvasSupport(){ 3 return Modernizr.canvas; }
上面代码第1行为将外部.js文件导入到HTML文件中,下面的代码是为了检测是否支持Canvas,而将canvasSupport()函数进行修改。这里将要使用modernizr.js方法,因此它提供了测试Web浏览器是否支持Canvas的最佳途径。
4.获得2D环境
var context =theCanvas.getContext("2d");
最后需要得到2D环境的引用才能操作它。HTML5 Canvas被设计为可以与多个环境工作,包含一个建议的3D环境。不过这里只用到了2D环境。通过getContex()方法取得context,然后在之后的绘制函数中大家便可以用context来设置各个属性了。
5.绘制函数
现在可以创建实际的Canvas API代码了。在Canvas上运行的各种操作都要通过context对象,因为它引用了HTML页面上的对象。大家在案例中所看见的“屏幕”就是定义画布的绘图区域。首先应清空绘图区域。
1 context.fillStyle="#ffffaa"; 2 context.fillRect(0,0,500,300);
上面的两行代码在屏幕上绘制出一个与画布大小相同的黄色方块。fillStyle()设置颜色,fillRect()创建一个矩形,并把它放到了屏幕上。在清空完绘图区域后,看一下绘制函数drawScreen()是如何开发的。
1 function drawScreen(){ 2 context.fillStyle="#ffffaa"; //背景 3 context.fillRect(0,0,500,300); //创建一个矩形 4 context.fillStyle="#000000"; //文字 5 context.font="20px Sans-Serif"; //设置字体的大小和字号 6 context.textBaseline="top"; //设置字体的垂直对齐方式 7 context.fillText("Hello World! ",195,80); //将测试文本显示到屏幕上 8 var helloWorldImage=new Image(); //添加2D图像 9 helloWorldImage.onload=function(){ 10 context.drawImage(helloWorldImage,155,110); } 11 helloWorldImage.src="pic/helloworld.png"; 12 context.strokeStyle="#000000"; //设置边框 13 context.strokeRect(5,5,490,290); 14 }
❑ 第2~7行设置了背景颜色与形状,之后声明了文字的颜色、大小和字号并设置了字体的垂直对齐方式,最后将测试文本显示到屏幕上。
❑ 第8~13行为添加图形。为了将图像显示到画布上,需要创建一个Image()对象实例,并且将Image.src属性设为将要加载的图像名字。在显示图像之前,需要等待图像加载完毕。设置Image对象的onload函数可以为Imageload创建一个回调函数。
由于上面几节已将本例中的重点代码介绍了,所以就不再将全部代码在这里重写一遍了,读者可以查阅随书资源中的Sample1_23案例进行学习。下面来看一下第一个Canvas程序的运行效果,如图1-23所示。
图1-23 案例Sample1_23效果
读者在第一次开发时肯定会遇到一些问题,还会有调试程序的步骤。但是这里不会将可能的错误全部罗列出,读者在开发中遇到问题时可以用前面提到的浏览器自带调试器或者firebug进行调试。
学完Canvas版“Hello World”的开发过程后,大家来进一步深入学习一下Canvas提供的一些绘制基本图形的API。看完这些内容后读者就可以开发一些2D的内容了,这里提供的为系统的API,读者只要认真学习都可以掌握。
1.6.4 Canvas中的基础图形
在看完第一个Canvas程序后大家对它已有了基本认识,HTML5 Canvas的使用是以强大的绘图、着色和基本二维形状变换为基础的。然而,可供选择的内建形状相对有限,程序员可以通过一组称作路径的线段来绘制出想要的形状。
现在学习一下新的内容,在Canvas上绘制一些基本图形。绘制这些图形基本上都会有相应的API,本案例中不同的图形会在不同的JavaScript文件中,相应的API在里边都会有所体现。读者阅读时结合着注释便能够轻松学会,现在看一下这部分的开发过程。
代码位置:随书源代码/第1章目录下的HTML5/Sample1_24.html。
1 <! DOCTYPE HTML> 2 <html><head><title>Sample1_24</title> 3 <script src="js/modernizr.js"></script> //导入js文件夹下的modernizr.js文件 4 <script src="js/arc.js"></script> //导入js文件夹下的arc.js文件 5 <script src="js/bezier.js"></script> //导入js文件夹下的bezier.js文件 6 <script src="js/line.js"></script> //导入js文件夹下的line.js文件 7 <script src="js/linejoin.js"></script> //导入js文件夹下的linejoin.js文件 8 <script src="js/rect.js"></script> //导入js文件夹下的rect.js文件 9 <script type="text/javascript"> //前面导入的为外部JavaScript文件, 这里为内嵌的JavaScript文件 10 var context; 11 function eventWindowLoaded(){canvasApp(); } //封装加载JavaScript的方法 12 function canvasSupport(){ //检测浏览器版本是否支持Canvas 13 return Modernizr.canvas; } 14 function canvasApp(){ //实际JavaScript的入口方法 15 if(! canvasSupport()){return; }else{ 16 var theCanvas = document.getElementById("canvas"); 17 context=theCanvas.getContext("2d"); } 18 drawScreen(); //绘制场景,不同的图形有不同的绘制方法,这里省略了其余的方法 19 function drawScreen(){ //绘制2D图形的方法 20 //画布背景色为白色,这不利于辨识,填充一个有颜色的区域便于标识 21 context.fillStyle="#aaaaaa"; //设置背景样式 22 context.fillRect(0,0,500,500); //创建一个矩形 23 context.fillStyle='#000000'; //文字 24 context.font='20px _sans'; //文字的大小和字号 25 context.textBaseline='top'; //设置文本垂直对齐方式 26 context.fillText("Canvas! ",0,0); }} //将测试文本显示到屏幕上 27 </script></head> 28 <body onload="eventWindowLoaded(); "> 29 <div style="position: absolute; top: 50px; left:50px; "> 30 <canvas id="canvas" width="500" height="500"> 31 若看到这个文字,则说明浏览器不支持WebGL! </canvas></div> 32 </body></html>
❑ 第2~8行引入了各图形的JavaScript文件。每个图形的绘制方法都封装在了不同的文件中,在绘制时调用不同的绘制方法即可。读者在测试本案例时只需将drawScreen()方法替换掉便能测试不同的图形了。
❑ 第9~26行为内嵌的JavaScript脚本。这部分是Canvas程序的入口,其中Canvas的id通过context来设置一些属性,并且将绘图区域清屏并设置了一个与画布等大的矩形以显示Canvas画布。
❑ 第28~32行为创建Canvas的过程。具体过程在前面几节中已分别介绍了,onload在页面加载完毕后调用JavaScript脚本,Canvas设置好其3个属性。
在程序中调用drawScreen()方法时需要注意的是,在程序开头导入的几个JavaScript文件,这些文件包含绘制圆、直线、曲线的一些图形API,读者可以自行查阅这些代码进行学习,其中的解释和注意事项在注释中都有详细介绍,这里便不再赘述。
HTML5 Canvas这里便介绍完毕,读者千万别以为就已经掌握了Canvas, Canvas是HTML5新增的元素,可以干的事情还有很多。本章只介绍了2D环境下的绘制图形,以后的章节才是Canvas的真正应用。