4.1 第一步:用easel.js来渲染

按惯例,要想表明某个程序能正常运作,应该输出“Hello World!”之类的文字。而easel.js是个图形渲染引擎,所以,我们打算在屏幕上绘制颜色随机的方块,以此来检验引擎是否正常。

现在需要以某种方式启动JavaScript脚本。可选的办法有很多,而且本书后续章节还会再介绍一些。我们可以把要运行的JavaScript代码全部放在<script>标签里。不过这种办法可能有问题,因为这些JavaScript代码也许会在所有元素尚未完全准备好的情况下执行,如此一来,脚本便会在运行的时候出错。还有一个办法是像程序清单4.2这样,在<script>标签里为window对象绑定JavaScript事件。尽管我们不打算采用此办法,但是仍然可以了解一下这段范例代码。

程序清单4.2 将init函数绑定到window

本章打算采用一种更为简单,但不太优雅的办法,那就是:像程序清单4.3这样,直接把JavaScript绑定到body标签的onload属性上。请根据程序清单中的粗体代码修改index.html文件。

程序清单4.3 以稍显突兀的写法来加载JavaScript代码

严守网页开发规范的人看到这里可能会惊呼,因为业界把这种写法贬称为“侵入式JavaScript”。此说法背后蕴含着的思考方式其实完全合理。由于我们在维护网页开发项目时,总想使其变得易于扩展一些,所以,最好是能把代码按其性质划分成内容层(HTML)、展示层(CSS)和行为层(JavaScript),并尽量将其隔离开,以保持代码的整洁与灵活。这种分层方式已经流行了一段时间,若有兴趣,可在网上搜索“unobtrusive JavaScript”与“JavaScript Patterns”(JavaScript模式)这两个词。不过我们还可以研究得更深入一些,以便知晓何时应该坚持优雅的写法,而何时又应该采用权宜的应急方案。有些时候,易扩展、灵活,且健壮的代码,是与“至简原则”  “Ya Ain't Gonna Need It”,简称YAGNI,直译为“你并不需要它”。——译者注 相冲突的,因此,我们应该明白:想实现同一个功能,可以有好几种不同的写法,而这些写法各有优势。onload等许多特性(其中也包括能够触发JavaScript代码的其他手段,比如onclick()、onMouseOver()等)经过这么多年还能留在HTML规范中,自然有其道理,所以,还是应该知道这种写法。

讲完这一点之后,我们回到绘制色块的问题上。如果打算用这种“侵入式”写法为body元素绑定onload()的话,那就得有init()函数才行。可以像程序清单4.4这样,于加载easel.js库所用的<script>标签下方再写一个<script>标签,使浏览器在加载此标签时,弹出含有“hello world”字样的警示窗。

程序清单4.4 添加script标签,并在其中定义init函数

在显示色块之前,还有一些代码要写。请按照程序清单4.5修改init()函数,使其内容变得更加丰富一些。刚才为了确认引擎是否能正常工作而写的那行“hello world”代码现在可以删掉了。

程序清单4.5 包含更多内容的init函数

这段代码需要理解的地方很多。我们逐行来讲解。首先,声明变量canvas与stage,前者用来表示HTML中的canvas元素,而后者则用来表示easel.js引擎所定义的Stage对象实例。init函数首先通过getElementById()这个原生的JavaScript方法(原生方法是指由浏览器而非easel.js等引擎所定义的方法)找到id属性为myCanvas的canvas元素,并将其赋给canvas变量。接下来,以canvas变量为参数(该变量对应于网页中的canvas元素)新建Stage对象,并把此对象赋给stage变量。然后,把drawSquare()方法的运行结果赋给square变量。我们还没定义drawSquare()方法,不过假设现在已经定义好了,那么其后这行代码会调用addChild()方法,把square变量加入stage对象中。方块加入之后,并不会立即显示,所以最后还得再调用stage.update()方法,把刚加入的square展示出来。

还算简单,对吧?接下来看看程序清单4.6中的drawSquare()方法。请把这段代码放在<script>结束标签的上方。

程序清单4.6 drawSquare方法

easel.js引擎所提供的图形绘制方法,其封装程度依然很低,不过用起来却比较容易。这段代码实际上是在操作shape对象,具体来说,是操作shape对象里面的graphics。setStrokeStyle()方法用于定义图形边线的宽度,beginStroke()方法的参数表示边线颜色,beginFill()方法用于指定图形内部的填充色;而rect()方法的四个参数则表示shape的横坐标、纵坐标、宽度及高度。最后,drawSquare函数把shape对象返回,这样的话,init()函数就可以把此对象赋给square变量并将其渲染出来了。

用浏览器打开index.html文件,会看到如图4.1所示的灰色方块。

图4.1 绘制灰色方块

灰色方块是很好,不过我们想令其变得更有色彩一些,并且想在每次刷新页面的时候变换填充色。所以,需要略微修改drawSquare()函数,并新增randomColor()函数(代码参见程序清单4.7)。

程序清单4.7 刷新页面时随机变换填充色

drawSquare()函数需要调用randomColor()函数来获取随机颜色。randomColor()以0~255之间的随机分量来调配颜色,供graphics.beginFill()函数所用。而Math.floor函数则可以把小数下调为整数。现在每次刷新页面时,所看到的方块颜色都是随机的(参见图4.2)。

图4.2 彩色方块

技巧

在看下个步骤之前,你或许还没分清哪些是JavaScript原生函数,哪些是由easel.js的API所引入的函数。没关系,其实这并不难区分,因为程序里出现的变量和函数名只可能有三种来源。第一种就是你自己定义的,它们应该能在你自己所写的代码中找到。第二种则是JavaScript的原生方法或原生对象,这种情况可以去https://developer.mozilla.org/网站查阅其用法。第三种情况,则是由easel.js这种程序库所引入的。在这种情况下,要想找到其文档或范例代码也很容易:我们只需在网上搜索“程序库名称docs”、“程序库名称documentation”、“程序库名称API”、“变量或函数名称程序库名称”等关键字即可。在编写JavaScript程序时,这几种不同类型的API都会用到,附录A详细讲解了此内容。

[1] “Ya Ain't Gonna Need It”,简称YAGNI,直译为“你并不需要它”。——译者注