代码改变世界

[译]《学习HTML5游戏编程》第一章

2011-12-12 09:25  AndrewCja  阅读(3140)  评论(2编辑  收藏  举报

HTML5介绍

 

HTML5是HTML下一版本的规范草案,它是它的前身HTML4 和XHTML的突破。在HTML5中一些元素被移除了,同时HTML5也不再基于旧的文本标记标准SGML。HTML5比HTML4更能兼容错误的语法,同时能让不同浏览器以相同的方式解析和展示格式错误的文档。这个版本的HTML增加了许多重要内容,比如内建的拖动支持以及音像元素。本章我们将讨论HTML5新增的特性及相关的JavaScript API。

跨越HTML基础

 

由Tim Berners-Lee发明的HTML(超文本标记语言)从1990年至今已有相当长一段历史了。来自HTML5Rocks slides (http://slides.html5rocks.com/#slide3) 的图1-1简要地展示了HTML的发展历程。

图1-1 HTML历程

虽然所有的进步对推动标准前进都至关重要,我们最为感兴趣的是1996年产生的JavaScript和2005年产生的AJAx。这些新特性使得网页从一个表示静态单向数据的媒体(如报纸和书)转变为一个允许双向交流的媒体。

JavaScript

 

JavaScript(前身为LiveScript,现在也被称为ECMAScript)由Netscape公司开发的浏览器脚本语言发展而来。它是一种基于原型的既像是面向对象又像是面向函数的弱类型的脚本语言。尽管名叫JavaScript,其更相似于C语言,虽然它也继承了Java的一些东西。

作为Sun公司(现在是Oracle公司)和Netscape公司之间关于推广脚本语言和Java Applet技术的协议的一部分,该语言被重命名为JavaScript。JavaScript被广泛用来编写客户端网页脚本,而与此同时,微软发布了和其并立的脚本语言,名叫Jscript,因为Sun公司已将"JavaScript"这个名称注册成为商标。Jscript语言相对于JavaScript作了一些修改并添加了一些新内容。

AJAX

 

AJAX(异步的JavaScript和XML)重新激起了人们对JavaScript编程的兴趣。曾经一度被认为是业余人士和脚本小子的AJAX已经帮助开发者解决了复杂的问题。

AJAX依靠的中心点是微软在1990年发明的XMLHttpRequest对象。XMLHttpRequest允许一个网站连接到远程服务器获取结构化的数据。与建立一系列静态页面不同,XMLHttpRequest能使开发者创建高度动态的应用程序。Gmail、Twitter和Facebook都是这种应用的例子。

我们正处于JavaScript的另一个复兴时期当中,主要的浏览器生产者都在将他们的JavaScript引擎的性能作为比较的指标。JavaScript作为一种主要的编程语言已经渗透到服务器端web组件,比如Node.js,以及移动应用框架WebOS和PhoneGap。

填补空白

 

即使是最好的标准,要被广泛采用也需要一段时间。为了不让缺失的特性限制创新,Google创建了Chrome Frame和Google Gears(下文将其简称为Gears),将先进的特性引进了旧版本浏览器中。

Google Gears

 

在2007年5月第一次发布的Google Gears,实现了HTML5规范草案的一些先进特性。在HTML5真正到来之前,许多应用程序在在一定程度上使用了Gears,包括Google的应用程序(Gmail、YouTube、Doc、Reader等等)、MySpace、Remember the Milk、WordPress、还有其他许多应用程序。Gears由若干个模块组成,这些模块将桌面应用程序的典型功能引进了浏览器。让我们花点时间来讨论这些功能特性。

在第一版发布中,Gears引进了Database、LocalServer、WorkerPool三个模块。Gears的Database API使用类似于SQLite的语法来为web应用创建关系型数据存储。数据被存储在特定的应用程序中,并用规范化的跨站脚本规则编译,以保证一个应用程序无法访问其域外的数据。LocalServer模块允许web应用程序将资源保存在本地缓存中和从缓存中获取资源,即使是在没有连接因特网的情况下也是如此。在网站的manifest文件中可以指定本地缓存提供什么样的资源。当请求的资源和manifest文件中某个URL相匹配时,Local Server模块将拦截请求,并从本地存储中提供请求的资源。

WorkerPool模块用于解决JavaScript密集型网站的普遍问题:长时间运行的JavaScript会阻塞网站和用户的交互。一个网页默认只有一个线程在运行,这对于短暂执行的突发动作(比如简单的DOM操作)通常不是问题。但对于长时间执行的任务,比如文件输入输出,或者从一台缓慢的服务器获取资源,其会阻塞web应用程序和用户的交互,同时会使得浏览器认为脚本响应过慢,应该被强制停止。WorkerPool模块将多线程计算的概念引进了浏览器,其创建的工作线程能执行任意JavaScript代码。工作线程能在彼此之间发送和接收信息,只要它们处于同一个WorkerPool中,它们就能在任务上相互协作。工作线程可以跨源执行,但受限于它们被获取的地方的策略。工作线程无法访问window对象的一些属性,比如Timer和HttpRequest,为了解决这个问题,Gears提供了自己的实现。

另一个有趣的API是Geolocation API。其试图通过IP地址、已知位置的Wi-Fi路由、通信基站和其他相关数据来定位访问者的位置。

Google在2009年11月份停止了Gears的主要开发,并将注意力转移到实现HTML5的相关特性。所幸的是,我们讨论的这些特性在某些层面上和HTML5是一致的。

Chrome Frame

 

Chrome Frame是Google的一个项目,其将Google的Chrome浏览器作为插件内嵌到不支持HTML5的IE6以及之前版本浏览器中。通过识别一个meta标签可以激活Chrome Frame。目前,即使在没有管理员权限的系统上也能安装和使用Chrome Frame。你可以从http://code.google.com/chrome/chromeframe/找到关于Chrome Frame的更多信息

使用WebSocket和Web Worker编程

 

HTML5规范增加了一组API,使得web应用之间能够相互通信,协同完成工作。其中,WebSocket允许web应用程序打开一条通道与web服务进行交互。Web Worker则使得web应用程序能够执行大量任务而不阻塞浏览器。

WebSocket

 

WebSocket能够在web应用程序和URI端点之间建立一条双向通道。Socket对象可以发送和接收信息,也可以响应打开和关闭事件。有其他几种方式也能够实现双向通信,包括Comet(使用了long polling技术的AJAX)、Bayeux和BOSH,不过这些方式不是HTML5 规范的一部分。

代码清单1-1创建了一个WebSocket与echo服务端点通信。创建Socket之后,我们接着创建了一些方法,它们分别在socket打开、关闭、接收到信息或者抛出一个异常时执行。接下来,socket发送了一条"Hello World!"消息,当浏览器接收到返回的消息后显示"Hello World!"。

代码清单1-1 使用WebSocket响应消息

var socket = new WebSocket(ws://websockets.org:8787/echo);

socket.onopen = function(evt) { console.log("Socket opened");};

socket.onclose = function(evt) {console.log("Socket closed");};

socket.onmessage = function(evt){console.log(evt.data);};

socket.onerror = function(evt) {console.log("Error: "+evt.data);};

socket.send("Hello World!");

Web Worker

 

HTML5中的Web Worker类似于Google Gear中的WorkerPool。与WorkerPool不同的是,我们不须要创建WorkerPool来存放Web Worker。代码清单1-2展示了如何创建一个简单的worker,以及怎样在worker上设置一个在接收到消息时执行的函数。代码清单1-2和1-3展示了如何使用Web Worker来创建一个能每隔两秒显示当前日期和时间的函数。

代码清单1-2 请求当前时间的网页

<!DOCTYPE HTML>

<html>

<head>

<title>Web Worker example</title>

Application Cache 5

</head>

<body>

<p>The time is now: <span id="result" /></p>

<script>

var worker = new Worker('worker.js');

worker.onmessage = function (event) {

document.getElementById('result').innerText = event.data;

};

</script>

</body>

</html>

 

相关的JavaScript文件worker.js显示在代码清单1-3中。

代码清单1-3 获取日期和时间的Worker.js文件

setInterval(function() {w

postMessage(new Date());

}, 2000);

 

我们从上面的两个代码清单中看到,worker可以使用postMessage()方法发送消息,还可以通过闭包onmessage来监听消息。另外,我们还能对错误做出响应,通过将函数绑定到onerror属性并在函数中执行terminate()方法来终结Web Worker对象。

Worker可以被共享,还能通过MessagePort发送消息。但和Web Worker规范的其他方面一样,这部分功能也还没形成稳定版本,而本书的示例也不须要使用到这些功能。因此,worker共享将作为本书的练习供有兴趣的读者研究。

Application Cache

 

Application Cache使应用程序能够在离线的状态下运行,这类似于Gears中的LocalServer特性。它们两者间的区别是应用程序缓存不使用JSON格式的文件,而是使用纯文本文件来指定缓存哪些文件。代码清单1-4展示了一个简单的用以指定缓存哪些资源的manifest文件。

代码清单1-4 应用程序manifest文件示例

CACHE MANIFEST

# above line is required, this line is a comment

mygame/game.html

mygame/images/image1.png

mygame/assets/sound2.ogg

 

Application Cache 能够响应以下几个事件:onchecking、error、cached、noupdate、progress、 updateready和obsolete,你可以监听这些事件以将应用程序的状态通知用户。Application Cache 能够让你开发的游戏更能应付出现断电的情况。另外,通过缓存资源,你开发的游戏能更加快速地启动,使玩家得到愉悦的体验。如果须要的话,还可以利用应用程序缓存让玩家在离线的状态下玩游戏。不过现在请先放下这些复杂的技术,在第11章"发布你的游戏"中,我们将更加深入地探讨如何使用应用程序缓存。

Database API

 

目前,可以通过多种方式使用HTML5来存储结构化的数据。这些方式包括Webkit浏览器的WebSQL API及其由Firefox带头的竞争对手IndexedDB API。

WebSQL API

 

WebSQL实现了一种类似于SQL的语法用以存储结构化的数据。目前WebSQL是以SQLitem为核心实现的,但这并不是一个特定的要求。

WebSQL中没有专门用于创建数据库的函数。可以通过调用openDatabase()函数并指定参数来打开一个数据库,如果指定的数据库不存在,一个新的数据库会被自动创建。例如,我们可以通过下面的语句来创建一个名称为myDB的数据库

var db = openDatabase("myDB", "1.0", "myDB Database", 100000);

这里,我们传递"myDB"作为名称,分配一个版本号"1.0",指定显示名称为"myDB Database",最后指定一个100KB的估计容量。我们还可以指定一个在数据库被创建时执行的回调函数,但这不是必须的。图1-2 展示的是Chrome浏览器开发人员工具中的Storage面板。在本书第二章"设置好你的开发环境"中,我们会执行上面那行代码,并对Storage面板做详细的介绍。

图1-2 Storage面板展示创建了的数据库

在窗口的右边我们可以执行任意SQL代码。如图1-3所示,我们创建了一个数据库表,插入一些数据,让后执行一条查询语句。

图1-3 在Storage面板上执行SQL语句

HTML5规范要求同时存在异步和同步的数据库连接与事务,不过这个规范没有被广泛支持。上面打开数据库的示例代码使用的是异步的数据库连接,若想要使用同步的数据库连接可以调用openDatabaseSync()方法,并传递和上面示例相同的参数。初始化数据库连接之后,对数据库事务的操作没有什么要特别注意的地方,只要知道通过调用transaction创建可读写的事务,调用readTransaction创建只读的事务就可以了。

请注意,同步的数据库连接目前还没有良好的支持,通常来讲,你应该使用异步的数据库连接。

IndexedDB API

 

IndexedDB直接将对象存储起来,这使得实现JavaScript版本的NoSQL数据库更加容易,如对象数据库MongoDB、CouchDB和SimpleDB。在编写本书的时候,IndexedDB API的实现还没有得到统一,存在不同的命名方式,对规范的遵守程度不尽相同。IE浏览器的实现方式要求安装ActiveX插件。本书建议你从http://nparashuram.com/trialtool/index.html#example=/ttd/IndexedDB/all.html查看该组API分别在Firefox、Chrome和IE浏览器中的示例。为Chome浏览器编写的代码大多数情况下也能在Safari中无缝使用。

Web Storage

 

Web Storage提供了一组用于在客户端存储数据的API,其方式类似于浏览器cookie。名称为localStorage的对象可以用于存储应用程序在重启时要使用的数据,名称为sessionStorage的对象用存储与会话相关的数据,这些数据在会话结束时会被清除。数据以键值对的方式存储。这个两个对象实现了列表1-1中列举的函数。

列表1-1 Web Storage函数

函数名称

描述

setItem(key:String, value)

用指定的参数值创建键值对。有些浏览器实现要求value参数是一条字符窜。

getItem(key:String)

返回key参数对应的键值对。

removeItem(key:String)

移除key参数对应的键值对。

clear()

清除storage对象中的所有键值对。

key(index:long)

返回索引对应的键。

 

每个storage对象都用length属性来指明键值对的数量。

Web Storage还提供了另一个接口,其可以替代列表1-1中getItem和setItem函数。该接口的使用类似于数组。我们可以使用下面的语句来为localStorage对象设置键值对:

localStorage['newspaper'] = 'The Baltimore Sun';

同时,我们可以使用上面语句的左边来获取键值对中的值:

localStorage['newspaper'];

在编写游戏的时候,我们可以使用Web Storage来保存游戏的得分排名榜,或者存储游戏的状态,以便在下次玩游戏时启用。

Geolocation

 

要跟踪用户的地理位置信息必须先通过用户授权,而Geolocation API中没有提供请求用户授权的函数。不过,浏览器会透明地替我们处理授权。当Geolocation API向一个它没有权限请求位置信息的网站请求位置信息时,一个上下文窗口将自动弹出以请求用户的授权。

我们可以通过下面的对象检查浏览器是否支持Geolocation API:

navigator.geolocation

如果geolocation是一个非null值,我们就可以用其进行定位。

通过位置对象可以计算出用户的地理位置信息,该对象包括一个名称为coords的坐标对象和一个用以表明何时取得位置信息的时间戳。列表1-2列出了坐标对象的一些属性。

 

列表1-2 坐标对象属性

属性名

属性值类型

描述

latitude

double

定位的纬度。

longitude

double

定位的经度。

altitude

double

定位的高度,单位为米。如果得不到高度信息,该属性值为null。

accuracy

double

经纬度的误差范围,单位为米。如果得不到经纬度的误差范围信息,该属性值为null。

altitudeAccuracy

double

高度值的误差范围。如果得不到高度值的误差范围信息,该属性值为null。

heading

double

设备移动的方向,单位为度(0°至360°, 包括边界)。如果得不到移动方向信息,该属性值为NaN。

speed

double

设备移动的速度,单位为米。如果得不到移动速度信息,该属性值为null。

 

当我们验证navigator上存在gelocation属性后,就可以很方便地获取设备的定位信息了。我们只需要调用getCurrentPosition方法并传递一个、两个或者三个参数就可以了。前两个参数都是函数,它们分别在成功获取位置信息和获取失败时执行。另一个参数是位置请求的选项设置。

代码清单1-5展示了如何获取位置信息,使用marker在地图上定位该位置,并以marker为中心画一个圆来突出定位的误差范围。

 

代码清单1-5 使用Geolocation画地图

if(navigator.geolocation) {

navigator.geolocation.getCurrentPosition(function(pos) {

var latitude = pos.coords.latitude;

var longitude = pos.coords.longitude;

var options = {

position:new google.maps.LatLng(latitude, longitude)

,title:"Your location"};

var marker = new google.maps.Marker(options);

var circle = new google.maps.Circle({

map:map, radius:pos.coords.accuracy

});

circle.bindTo('center', marker, 'position');

marker.setMap(map);

map.setCenter( new google.maps.LatLng(latitude, longitude));

},

function(error) {

console.log(error.message);

});

}

 

在验证navigator上存在gelocation属性后,我们首先试图获取设备的位置信息。在这个例子中,我们传递两个函数作为getCurrentPosition的参数,它们分别在成功获取地理位置信息以及获取失败或者用户拒绝授权定位时执行。在获取纬度和经度信息后,我们在该经纬度位置上创建了一个marker,并加了"Your location"标题。我们在该标志上加了一个圆,该圆的半径等于该定位的经纬度误差范围。最后,如果出现错误,我们的错误处理函数会将错误信息打印到控制台。图1-4展示的是使用了OpenStreetMap标题集的定位示例。

在上面的例子中我们并没有使用options对象作为参数,但须要的话我们可以把它作为第三个参数,用以对所要获取的数据进行设置。我们还可以设置一个函数作为监听器,在watchPosition函数每次返回位置变化时执行。要提醒的是,Geolocation是一个很耗资源的API,要小心谨慎地使用它,并注意使用缓存。

图1-4 浏览器中的地理定位

我们可以使用geolocation来创建分地区的游戏排行榜,也可以使用它在多玩家游戏中匹配地理上想接近的玩家。

使用Notification提示用户

 

在HTML4中,和用户进行信息交互的方式有限,其主要有两种:alert一个窗口来提示消息,或者通过一个div元素来提示消息。所有的浏览器都支持弹出一个窗口的方式,但这种方式会给用户造成困惑:弹出窗口会强烈地引起用户注意,另外,用户必须先关掉弹出窗口后才能继续做自己要做的事情。如果一个游戏玩家因为被弹出的消息窗口挡住视线,而使自己所扮演的游戏角色死去,那他将会非常恼怒。使用一个div元素来提示消息会相对好一些,但这种方式没有标准的做法,并且这种方式很容易被用户疏忽掉。第一种消息提示方式过于唐突,而第二种则可能难以让用户注意到。所以必须有一种折中的方式。

在Mac OS X 系统、Ubuntu系统或者装有相关插件的Windows系统中,应用程序可以配置并提示消息,以通知用户重要的事件或变化。图1-5展示了这种消息提示方式的例子。

图1-5 桌面应用程序的消息提示

和桌面应用程序的消息提示一样,web notifications能够在显示消息时使用背景图片。

请求授权以展示notifications

 

在我们向用户展示notifications之前必须先取得用户的授权。要求用户授权可以防止用户受到恶意notifications的骚扰。下面的代码用于在展示notifications前请求授权:

window.webkitNotifications.requestPermission();

这行代码使浏览器提示用户是否授权notifications,如图1-6所示。在调用上面的方法时,我们可以不传递参数,也可以传递一个函数作为参数,用以在用户确认或者否定授权时执行。

图1-6 web notification 授权提示

同时,我们还可以通过执行下面的代码来验证授权:

window.webkitNotifications.checkPermission();

checkPermission()方法返回一个整数以表明授权级别,如列表1-3所示:

 

列表1-3 Notification 授权级别

常量名称 值

PERMISSION_ALLOWED 0

PERMISSION_UNKNOWN 1

PERMISSION_DENIED 2

 

看到webkitNotifications这个对象名称,你可能会猜想notifications能够在基于Webkit的浏览器中执行,比如Google的Chrome和苹果的Safari。事实上,虽然Safari是基于Webkit的,但此浏览器并没有实现Notification API。如果按照规范来实现,则以上对象不应叫做webkitNotifications,而应该简称做notifications。

创建Notification

 

可以创建两类notification:简单的和HTML的。简单的notification用以显示简单的消息以及可选的标题和图标,而HTML notification用以显示任意URL指定的资源。例如,我们可以通过执行下面的代码来创建一个简单的notification:

var msg = window.webkitNotifications.createNotification(

'', 'Test Notification', 'Hello World'

);

刚创建的notification的标题为"Test Notification",提示内容为"Hello World"。我们传递了一条空字符窜作为图标参数,这样接口会忽略这个参数。在其他参数上也可以传递空字符窜,如果你不想显示该参数的话。若你没有传递任何参数给createNotification方法,会导致消息内容显示为"undefined"和一个缺图标志。图1-7展示了在浏览器中执行的notification。可以看到,它的外观非常简洁,除了传递基本的信息作为参数,我们不能对外观有所控制。

图1-7 简单的web notification

前面说到,HTML notification可以从任意的URL获取资源作为内容,比如获取一个网页或一张图片。下面的代码创建了一个HTML notification,并从指定的URL获取资源作为内容。

var msg =window.webkitNotifications.createHTMLNotification(

'http://example.com'

);

HTML notifications没有提供修改宽高的方法,对于小电脑屏幕,除非指定的URL所对应的资源能根据屏幕调整自身大小,否则将会出现滚动条。对于16801050的屏幕,默认的像素宽高大约为300像素(宽)* 50像素(高)。在编写本书时notifications API仍然处于草案阶段,所以上面所诉的宽高很可能会发生变化。在确切的宽高属性被添加到notifications之前,我们最好还是用简单的notifications。

和Notifications交互

 

有两个基本函数可以控制notifications:show()函数用来将notifications呈现给用户,cancel()用来影藏notification(如果当前它是可见的)或阻止notification显示出来(如果当前它是不可见的)。还可以设置函数来监听notification事件。列表1-4列出了可以响应特定事件的函数:

列表1-4 Web Notification函数

函数名                        描述

onclick 如果所用浏览器支持的话,当notification被点击时该函数会被执行。尽量避        免使用该事件。

onclose 当close事件被触发时该函数被执行,比如用户关闭了notification或者执行代        码关闭了notification。

ondisplay 当show()函数被调用,notification显示给用户后,该函数被执行。

onerror 当调用show()函数出现错误时,该函数被执行。

 

你可以访问以下网址查阅当前规范草案的状态:

http://dev.chromium.org/developers/design-documents/desktop-notifications/api-specification

媒体元素

 

HTML刚被设计出来的时候,只能用来显示普通文本。显示图片的功能是后来才出现的。所以不难理解为什么须要安装一个浏览器插件才能播放音频或者视频。在大多数情况下,这个插件就是flash。HTML5试图通过引进audio和video标签来解决须要安装插件的问题。

Audio和video标签能让我们直接在浏览器里播放音频和视频。同时,这两个标签提供了一组属性用于控制播放状态。下面一行代码是使用内嵌媒体的最基本形式(具体是使用一个音频文件):

<audio src="song.mp3" autoplay />

这行代码创建了一个audio元素,使用song.mp3作为播放资源,并命令网页"自动播放"音频。它和下面的JavaScript代码具有同样的效果:

var song = new Audio();

song.src = "song.mp3";

song.autoplay = true;

song.load();

 

控制媒体

 

除了前面的例子中列出的autoplay属性外,还有其他几个属性可以用于控制媒体。例如:

<video src="vid.avi" controls />

或者

var vid = new Video();

vid.src = "vid.avi";

vid.controls = true;

告诉浏览器提供一组默认的控制按钮,用于启动和暂停播放,设置音量大小,和拖曳播放进度。如果不想使用这个属性,开发者可以使用列表1-5和列表1-6列举的函数和属性来设置自定义的控制按钮。

列表1-5 媒体标签函数

函数名                     描述

Play()    从当前位置开始播放媒体并设置paused属性值为false。

Pause() 暂停播放媒体并设置paused属性值为true。

Load() 复位媒体元素,并应用相关设置,比如预抓取。

 

列表1-6 媒体元素属性

属性名            属性值类型            描述

currentTime 整数            设置播放的媒体流的位置

duration        N/A(只读)        指示媒体资源的长度,单位为秒

loop            true或false    设置当播放到媒体流末端时是否重新播放媒体

autoplay        true或false    设置是否尽快地自动播放媒体

muted             true或false    设置是否能够把音量设置在0.0

 

上表并没有列出媒体标签的所有属性,为了简洁,只列出了最有用的属性。想要查阅所有属性,请访问HTML5规范草案http://dev.w3.org/html5/spec。

处理不支持的格式

 

在编写本书的时候,并非所有浏览器的audio和video标签都支持相同格式类型的音频和视频文件。一个浏览器不支持某种格式的原因可能是此格式太老了,或者此格式是该浏览器偏爱的格式的竞争者,或者是由于专利限制的原因,此浏览器的产商不能处理此格式。不过,媒体标签提供了几种方式处理此问题。

枚举多种格式资源

除了指定单个资源文件,开发者也可以同时指定多个资源文件以让浏览器选择一个合适的进行播放。在下面的代码段中,video标签列举出了两个不同格式的资源。如果两种格式都不被支持,或者浏览器连video标签都不支持,则向用户显示相关信息。

<video>

<source src="video.ogv" />

<source src="video.avi" />

<!— Neither is supported, can show message or fallback to Flash —>

<div><span>Use a modern browser</span></div>

</video>

 

对于静态内容页面,可以枚举出多种格式资源,但对于动态内容页面却不能这样做。在动态页面中,建议使用Modernizr工具。在第二章中我们会更加深入地探讨Modernizr,不过先让我们来看看一些基础知识。

使用Modernizr

Modernizr (www.modernizr.com)可以在运行时检测浏览器的功能,并将相关属性注入JavaScript对象。要看看浏览器是否支持播放音频或视频,可以通过检查Modernizr.audio或Modernizr.video的值是否为true来判断。

检查浏览器是否支持某种格式的媒体文件的方式略有不同。可以通过检查Modernizr.audio.mp3的值来判断是否支持MP3文件,但该属性值不是true或false。HTML5规范要求浏览器返回一个值来表明它对该格式的支持程度,这个值可以是"probably"、"maybe"或者一条空字符窜。我们可以在条件判断子句中使用Modernizr.audio.mp3,因为非空字符窜的计算结果为true,空字符窜的计算结果为false。

HTML5 绘画API

 

绘画API是HTML5规范中的有趣领域,Cavas、SVG和WebGL分别提供了位图、矢量和3D的绘画功能。

Canvas

 

canvas元素原本是苹果公司在Webkit浏览器中的一个扩展。此样式引擎使得Safari浏览器和Chrome浏览器能够显示汽车仪表盘。它后来被Opera、Firefox和其他浏览器所采用,最终成HTML5规范的一部分。不久前发布的IE9测试版也支持canvas,虽然在支持的全面性上不如前面所诉的几种浏览器,但这样一来,可以说几乎所有主浏览器都支持canvas元素了。

可以这样简单地理解canvas元素:它是一个具有宽高属性的可绘画区域,通过使用JavaScript来绘制和移动复杂的图表或图像。JavaScipt语言提供了进行2D绘画的函数集合,并且JavaScript的绘画代码和ActionScript的绘画代码在形式上非常接近。使用ActionScript绘制的Flash图片或动画,要转移到JavaScript中只需要少量的代码修改。在第五章"使用canvas标签来构建游戏"中,我们将更加深入地探讨canvas元素。

SVG

 

SVG (Scalable Vector Graphics)是一个成熟的W3C标准,用于绘制静态或动态图像。在HTML5中,可以不使用object标签或embed标签,而直接把SVG内联到网页文档中。SVG使用各组数学公式来绘制弧线、直线、路径、长方形等各种基本图形元素,并用这些基本元素组合成更加复杂的图像,这样的图像能够进行缩放且在各种尺度下保持同样的质量。相对于放大后质量会下降的位图图像,矢量图像具有很大的优势。

SVG采用了和canvas元素很不一样的绘画机制,它使用XML格式的文件来表示绘画,而不是使用JavaScript代码。虽然XML不能简洁地表示数据,文件中可能包含很多重复的节点,但通过压缩XML文件,可以很大的减少它的大小。和canvas元素一样,SVG图像和用户的交互可以用JavsCript编程来完成。在IE9之前,其他版本的IE浏览器支持一种名叫VML的不标准的矢量格式。直到IE9发布之后,所有的主流浏览器基本上都支持SVG 1.1。在第六章"使用SVG和RaphaëlJS来构建游戏"中,我们将深入地介绍SVG。

WebGL

 

WebGL是一个用于3D绘画的JavaScript API。它使得开发者能够分析图像硬件资源,全面细致地控制图像渲染通道。WebGL由Khronos组织进行管理,在语法上大部分和OpenGL 2.0 ES一样。在本书被编写的时候,IE6及其以后版本浏览器以及稳定版的Opera和Safari浏览器都不支持WebGL,而稳定版的Firefox和Chrome/Chromium浏览器以及开发版的Opera和Safari浏览器支持WebGL。在第七章"使用WebGL和Three.js来创建游戏"中,我们将深入地介绍WebGL。

使用microdata传达信息

 

页面解析应用程序或API能够识别使用了microdata的标记并做出响应。例如,搜索引擎返回的使用了microdata的标记能够被浏览器扩展或JavaScript程序解析,从而更好地向患有视弱或色盲的用户传达信息。Microformats概念在microdata之前出现,它用于同样的目的。Microformats和HTML5 microdata的关键不同就是数据被标记的方式。如代码清单1-6所示,microformats使用class属性来指明对象上具有哪些字段。

代码清单1-6 hCard Microformat 示例

<div class="vcard">

<div class="fn">James Williams</div>

<div class="org">Some Company</div>

<div class="tel">650-555-3055</div>

<a class="url" href="http://example.com/">http://example.com/</a>

</div>

 

Microdata具有同样的作用但使用了稍微不同的标记方式。与使用class来标记对象的属性不同,microdata使用了itemprop关键字,用来标记一个独立的单元。microdata本质上就是键值对的集合。代码清单1-7为一个microdata示例,itemtype用来标明对象是如何定义的,具有哪些有效属性。你可以使用microdata在游戏排行版页面上组织用户名和分数数据,或使用其来组织操作指南和截图数据。

代码清单1-7 Microdata 示例

<p itemprop="address" itemscope

itemtype="http://data-vocabulary.org/Address">

<span itemprop="street-address">1600 Amphitheatre Parkway</span><br>

<span itemprop="locality">Mountain View</span>,

<span itemprop="region">CA</span>

<span itemprop="postal-code">94043</span><br>

<span itemprop="country-name">USA</span>

</p>

 

总结

 

HTML5使我们和浏览器的交互方式发生了巨大变化。这一章介绍了对我们有用的重要内容。我们学习了Google Chrome Frame如何使IE浏览器能使用HTML5薪特性,也学习了绘画编程的各种方式。

在这一章里挖掘HTML5的过程中,除了学习它的绘画API,我们还学习了能够让我们运行计算密集型任务而不阻塞浏览器的新特性,在应用程序间建立双向通信通道的方法,以及如何使web应用程序能在离线状态下运行。

你可以到这里www.informit.com/title/9780321767363下载本章的示例代码。