HTML5 和 CSS3 Web 演化入门指南(二)

原文:Beginning HTML5 and CSS3 The Web Evolved

协议:CC BY-NC-SA 4.0

四、更丰富的内容标记方法

尽我们所能烤出最好的蛋糕

正如我们在第一章中所强调的,创建一个高质量的网站需要技巧,而我们技巧的很大一部分就是知道如何使用相关的工具。因为 HTML 是“网络琐事”的基础,所以对它非常熟悉是非常必要的。虽然《??》第三章中的新语义元素——以及我们将在《??》第五章中涉及的<video><canvas>等明星——得到了很多关注,但 HTML5 也提供了许多小的补充和变化。它们可能不那么令人兴奋,但是它们会帮助你的工作流程更加顺畅。这些添加和更改包括您将一直使用的元素和适合某些内容的新元素。

为了与“HTML5 作为一种进化”保持一致,改变后的 HTML 4 元素通常会重新调整,以更好地适应不断发展的 Web。还有一个潜在的驱动力是媒体独立性——确保每个元素都将传达相同的语义,而不管使用的是视觉、听觉还是触觉媒体。虽然这可能使定义看起来有点笼统或模糊,但它对增加网络的包容性至关重要。随着越来越多的人使用互联网,并在更多不同的设备上使用互联网,这将变得越来越重要。

本章涵盖了已经被修改、重新定义,甚至被废弃的 HTML 4 元素;处理块级链接;查看一些新的文本级元素;并以扩展 HTML5 的方式结束,包括使用微格式和微数据。让我们从一些最常用的标记工具的重新调整开始。

Ex-表象元素和朋友

虽然许多 HTML 4 元素在本质上没有改变地被引入 HTML5,但 HTML 4 的表示元素要么已经过时(被 CSS 取代),要么被赋予了新的语义。这样做是因为他们的表象定义是基于他们在屏幕上的样子,这对辅助技术的用户没有帮助,比如有视觉障碍的人。HTML5 解决了这个问题。

首先让我们来看看旧的字体样式元素<i><b>,并将它们与语义中坚<em><strong>进行比较。

  • <i>为斜体,现在用于表示*“变声”、“??”的文本,如外来词、技术术语和分类名称。*
  • <b>为粗体,现在为*【文体偏移】*文本,如关键词、评论中的产品名称,或一篇文章的标题。
  • <em>过去是强调,现在是为了强调,比如你发音不同的东西。
  • <strong>表示更强的强调,现在表示非常重要(基本相同)。

我们还将看看 HTML5 中的另外四个元素,它们已经被变形为与媒体无关的语义。

  • <small>用于较小的文本,现在用于侧边注释,如小字。
  • <hr>是一条横线,现在用于段落级主题分隔符。
  • <s>用于删除线,现在用于不再相关或准确的内容*(我们将简要介绍<del><ins>进行比较)。*
    ** <u>用于带下划线的文本,现在用于一段文本,该段文本带有未明确表达的、尽管已明确呈现的非文本注释;请继续阅读,了解这到底意味着什么!*

*#### 赋予了< i >和< b >元素新的语义

In HTML 4、<i><b>是字体样式元素([j.mp/html4-fse](http://j.mp/html4-fse)<sup>1</sup>)。然而,它们现在有了语义,当然它们的默认风格可以通过 CSS 改变(例如<b>不一定要加粗)。因为这个**,我们建议添加有意义的 CSS 类名**,以便以后更容易改变样式。

元素

<i>元素表示一段可选语音或语气的文本,或者以指示不同文本质量的方式偏离正常散文。

生活标准,WHATWG ( [j.mp/html5-i](http://j.mp/html5-i)<sup>2</sup>)

通常斜体的东西包括外来词(使用属性lang="")、分类和技术术语、船名、脚本中的内嵌阶段说明、一些音乐符号,以及在内嵌表示思想或手写文本时。图 4-1 、 4-2 和 4-3 显示了示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-1。**用< i class=“voiceover” >表示画外音(备选语气)


1

2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-2。**用< i lang=“ja-latn” >表示从外文音译过来的散文(其中 lang="ja-latn "为日文音译)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-3。**使用< i class=“taxonomy” >作为分类名称

要检查字符集的lang=""值,您可以使用 W3C 的 Richard Ishida 开发的优秀的语言子标记查找工具([j.mp/subtags](http://j.mp/subtags)<sup>3</sup>)。

只有在没有更合适的方法时才使用<i>,比如用<em>来强调文本;<strong>对于具有语义重要性的文本;<cite>用于引文或参考书目中的标题;<dfn>为一个词的定义实例;而<var>为数学变量。使用 CSS 而不是斜体的文本块,如旁白,诗句,图标题,或块报价。记住使用class属性来标识元素被使用的原因,这使得重新设计特定用途的样式变得容易。你可以使用属性选择器(例如[lang="ja-latn"])在 CSS 中定位lang,我们在第八章的中已经介绍过了。外国散文的完整句子一般应在自己的段落(或<blockquote>)中加上引号,并且不应使用<i>。请将lang属性添加到包含元素中。

元素

<b>元素表示出于实用目的而引起注意的文本范围,没有传达任何额外的重要性,也没有替代声音或语气的含义。

生活标准,WHATWG ( [j.mp/html5-b](http://j.mp/html5-b)<sup>4</sup>)


3

4

对于仅仅看起来不同的<b>文本,不需要使用font-style: bold;。其他样式可以包括圆角背景、较大的字体大小、不同的颜色或格式,如小型大写字母。图 4-1 中的脚本包含了一个这样的例子,因为<b class="character">被用来表示谁在说话或叙述。

你可以在评论中使用<b>作为产品名称,在文档摘要中使用关键词,在复杂或传统设计的页面上使用初始文本,如图 4-4 和图 4-5 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-4。**使用< b class=“opening-phrase” >将 versal(首字下沉)与文本连接

伪元素选择器:first-letter用于创建 versal。在这种情况下,开头的短语被加粗只是出于文体上的原因。如果它在语义上很重要,<strong>或其他元素会更合适。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-5。在这种情况下,CSS 伪元素选择器:first-line 更合适

虽然我们可以使用<b>在第一个单词、短语或句子上应用传统的印刷样式,比如小型大写字母,但是 CSS 伪元素选择器:first-line更适合于像图 4-5 这样的情况(更多细节参见第八章)。

只有在没有其他更合适的元素时才使用<b>,比如对于语义重要的文本使用<strong><em>用于强调文本(带有“重音”的文本);<h1> - <h6>为封号;和<mark>用于高亮或标记的文本。对标签云的列表项使用类。为了重现传统的印刷效果,在适当的地方使用 CSS 伪元素选择器,如:first-line:first-letter(参见第八章)。同样,记住使用class属性来标识元素被使用的原因,这使得重新设计特定用途的样式变得容易。

和< strong >元素

虽然<em><strong>基本保持不变,但它们的含义有了细微的变化。在 HTML 4 中,它们意味着强调强烈强调。现在它们的意思已经被区分为代表强调(比如你发音不同的东西)的<em>和代表重要性<strong>

元素

em 元素表示其内容的重音。

生活标准,WHATWG ( [j.mp/html5-em](http://j.mp/html5-em)<sup>5</sup>)

这里所说的“压力”是语言学上的;如果说出来,它会强调一个词的发音,可以改变句子的细微差别。例如“现在就给医生打电话!”医生强调,也许是在回答某人的提问“她看起来很渴,我应该叫顺势疗法吗?”相比较而言,“现在叫医生*!”将重点改为快速完成。*

*使用<strong>来表示重要性,当你想要斜体字而没有强调的意思时,使用<i>。如果一个<em>元素出现在已经用<em>强调的文本中,嵌套的级别代表相对的强调级别。

元素

强元素表示其内容非常重要。

生活标准,WHATWG ( [j.mp/html5-strong](http://j.mp/html5-strong)<sup>6</sup>)

没什么好说的,真的——这是我们都非常熟悉的。通过嵌套<strong>元素来表示相对重要性,并使用<em>代替强调文本,使用<b>表示“风格偏移”或加粗但不更重要的文本,使用<mark>突出显示相关文本。


5

6

<小>元素

<小>元素代表侧边注释,比如小字。

生活标准,WHATWG ( [j.mp/html5-small](http://j.mp/html5-small)<sup>7</sup>)

<small>现在是侧边注释,相当于<aside>的内嵌部分——不是页面主要焦点的内容。一个常见的例子是行内法律术语,比如页脚中的版权声明、免责声明或者(如图图 4-6 )许可信息。也可用于归因。不要用于块级内容(段落、列表等)。),因为这将被视为主要内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-6。**使用满足字体许可协议的要求

另一个例子是关于一个属性,就像这样:

<small><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution Share-alike license</a></small>

<small>文本不需要比周围的文本小。如果你只是想要较小的文本,用 CSS 代替。仅对内嵌内容使用<small>。最后,<small>不影响<em><strong>的语义。


元素

hr 元素代表段落级别的主题中断。

生活标准,WHATWG ( [j.mp/html5-hr](http://j.mp/html5-hr)<sup>8</sup>)


7 [www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-small-element](http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-small-element)

8

“段落级”位表示一个文本块,如<p><ul>,但不包括例如内联内容或标题。主题中断是主题的变化,如小说中场景之间的变化。<hr></section><section>语义相同,所以在对元素和标题进行分段之前或之后,最好使用 CSS 而不是<hr>。然而,你可以在任何可以使用<p>的地方使用它。虽然现在还没有广泛使用(考虑到默认浏览器的单调渲染),但是可以通过 CSS 用一个图像来代替它,如图 4-7 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-7。**样式< hr >通过使用 CSS:HR { height:24px;背景:URL(’ floride . png ')不重复 50% 50%;边距:3em 0;边框:0;}

无论如何,IE7 及以下版本通过在图像周围添加边框来实现其声誉,但这通常可以解决([j.mp/hr-ir](http://j.mp/hr-ir)<sup>9</sup>)。或者,您可以通过 IE7 及更低版本的样式表隐藏它。最后,如图 4-8 所示,如果主题中断明显(例如,在博客评论之间)或者预期用途仅仅是演示性的,那么<hr>是不合适的。添加一个 CSS 边框或背景图片(可能使用:before:after,我们在第八章的中提到过)到另一个元素中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-8。 Cork’d.com 在标题上使用装饰性的 CSS 背景图片。这里不是使用<人力资源>的好地方。


9

元素,连同< del >和< ins >

<s>元素最初在 HTML5 中被废弃,但是随着语义用例的出现,它在最近才回归规范。<s>的定义很简洁。

s 元素表示不再准确或不再相关的内容。

生活标准,WHATWG ( [j.mp/html5-s](http://j.mp/html5-s)<sup>10</sup>)

最初,这个角色将由<del>元素覆盖,它被定义为

del 元素表示从文档中删除。del 元素不应该跨越隐含的段落边界。

生活标准,WHATWG ( [j.mp/html5-del](http://j.mp/html5-del)<sup>11</sup>)

但是,语义略有不同。<s>是指曾经准确或相关,但现在不再准确或相关的内容,并且被留下来提供上下文。<del>是指作为文档编辑的一部分(无论出于何种原因)已被标记为从文档中删除的内容,不需要提供上下文,甚至可能不会向读者显示或传达。<s>的例子包括过时的价格或售罄的事件列表。

`


  1.   
  2. Early bird (ends Apr 6): $799

  3.   
  4. Middle bird (Apr 7~May 1): $899

  5.   
  6. Late bird (May 2~May 23): $999

`

既然我们在讨论<del>,那就让我们也简单看看它的孪生兄弟<ins>


10

11

ins 元素表示对文档的添加。ins 元素不应该跨越隐含的段落边界。

生活标准,WHATWG ( [j.mp/html5-ins](http://j.mp/html5-ins)<sup>12</sup>)

<del><ins>是不常见的元素,因为它们可以用作短语或流元素,所以它们可以放在<p>元素内部或包含<p>元素。“不应该跨越隐含段落边界”的告诫告诉我们不要同时使用它们,或者,从字面上看,不要从一个<p>元素内部到另一个<p>元素内部。

`

Be careful using ins and del. They shouldn’t cross a paragraph boundary.

You have two options. Use an ins or del element inside each containing element, or one ins or del element outside.

Be careful using ins and del.**** They shouldn’t cross a paragraph boundary.****

****You have two options.**** Use an ins or del element inside each containing element, or one ins or del element outside.


  

Be careful using ins and del They shouldn’t cross a paragraph boundary.


  

You have two options. Use an ins or del element inside each containing element, or one
ins or del element outside.



  

Be careful using ins and del. Use an ins or del element inside each containing element,
or one ins or del element outside.


`

12

我们还必须小心在列表和表格中使用它们,例如,它们应该将内容包装在<li>元素和而不是元素中。

<del><ins>都可以有两个可选属性。cite属性用于添加提供更多信息的页面的 URL(比如解释编辑背后的原因)。

<del **cite="/edits/r102.html"**>

datetime属性用于记录编辑的日期和时间。格式是:

year-month-date then T then hour:minute:second then a timezone

考虑下面的例子(这些日期时间是相同的时间,但是在不同的时区):

<ins **datetime="2012-03-05T23:16:00Z"**> <ins **datetime="2012-03-06T08:16:00+09:00"**>

当我们讨论<time>元素时,我们将很快再次遇到datetime属性。

元素

<s>一样,<u>元素最近从过时部分返回,定义如下:

u 元素表示一段文本,该段文本带有一个未明确表示的(尽管是明确呈现的)非文本注释。

生活标准,WHATWG ( [j.mp/html5-u](http://j.mp/html5-u)<sup>13</sup>)


13

具有这些“非文本”注释的文本的一些例子包括中文专有名称标记,指示拼写检查反馈,以及指示罗马化的非西方姓名的姓。除了这三种用途,几乎可以肯定还有更合适的元素可以使用,但它是我们工具箱中的又一个工具。记住任何语义都应该出现在 HTML 层。虽然这些用例可能看起来多种多样,但重要的部分是文本被标记以引起读者的注意——他们将在上下文中理解它。

最后,与所有具有默认浏览器样式的元素一样,没有什么可以阻止您使用 CSS 将默认下划线样式更改为更合适的样式。例如,拼写检查器通常用红色虚线下划线来指示拼写错误,而罗马化的日本姓氏可以用大写字母来指示。这些很容易用<u class="spelling-error"><u class="family-name">和一点 CSS 来应用,我们会在第七章中发现。

表现元素:过去时代的遗迹

正如我们所看到的,HTML 4 的表示元素<b><hr><i><s><small><u>在 HTML5 中被重新定义为表示,具有与它们的典型用法相关的有用的媒体无关的语义。HTML 4 贬低或不鼓励的其他表示元素——<basefont><big><font><tt><strike>——在 HTML5 中已经过时。用 CSS 代替。

与<一个>元素的块级链接

超链接是 HTML 最初的“杀手级应用”。然而,从历史上看,在一个<a>元素中链接多个文本或其他内联内容是不可能的。这也是一个可访问性问题,因为一个大的可点击区域对那些使用鼠标有困难的人或任何使用触摸感应手机浏览的人来说是一个很大的帮助。除了<a>元素之外,Internet Explorer 6 无法在任何东西上设计:hover的样式,这也加剧了这个问题。

我们的解决方法包括制作链接display:block;并用填充物填充它,或者给几个元素添加单独的链接,给人一个大的可点击区域的印象。然后就是把所有东西包装在一个链接中,尽管根据规范(和验证)这是不正确的。

然而,总的来说,它实际上是有效的。因此,为了与 HTML5 的实际倾向保持一致,这种灰色地带技术已经成为规范的一部分。现在,您可以将流内容正式包装在一个<a>元素中,前提是它不包含任何交互式内容,包括表单元素,尤其是其他链接。这很容易做到,并导致 Internet Explorer < 8 的问题,所以注意不要将一个链接嵌套在另一个链接中。

a 元素可以围绕整个段落、列表、表格等等,甚至整个部分,只要其中没有交互内容(例如,按钮或其他链接)。

生活标准,WHATWG ( [j.mp/html5-a](http://j.mp/html5-a)<sup>14</sup>)

编写块链接

现在,如果我们想把标题中的几个东西变成一个块链接,这很容易。传统上,建立一个 block 链接需要很多链接和 CSS 体操。

`

       

Space monkeys

    

Going were no primate has dared to go

      A brave money all suited up
`

在 HTML5 中,你可以在任何地方添加链接——简单多了。

<!-- HTML5 block-level link --> <a href="/" class="block-link">   <header>     <hgroup>       <h1>Space monkeys</h1>       <h2>Going were no primate has dared to go</h2>     </hgroup>     <img src="" alt="A brave money all suited up">   </header> </a>


14

默认情况下,链接被视为{display:inline;},因此您可能需要设置{display:block;}{display:inline-block;}来应用一些样式。像块级链接中的<h1>这样的块级元素不会继承一些链接样式,所以你可能需要使用inherit来显式声明它们,比如h1 {background-color:inherit;}.你可以使用像<a class="block-link">这样的class名称来实现。

火狐浏览器警告< 4(留给后人)

这一切听起来很棒,但像往常一样,有一个或两个小皱纹抓住我们。在 Firefox 4 之前的 Firefox 版本中(它展示了一个基于 HTML5 的新 DOM 模型),如果块级链接的第一个孩子是我们在第三章中遇到的新 HTML5 元素之一,那么块级链接将被关闭,并且将为每个块级元素添加单独的内联链接。虽然包含的内容仍然是链接的和可用的,但这通常也意味着块级链接的:hover等样式看起来不太正确。

一个解决方案是在块级链接中添加一个<div>包装器(或者另一个 HTML 4 元素)。

`


  
**    
**
      
        

Title


        

Subtitle


      
**    
**
  

`

Firefox 3.x 处理块级链接中的标签不匹配错误……很差。如有疑问,请验证。

不幸的是,使用<div>包装器并不是灵丹妙药。由于 Firefox 神秘的“数据包边界”错误,这个问题仍然存在很小的可能性,在 Firefox 4 中再次得到了修复。这只是偶尔出现,并不是在每个块级链接上(这使得测试非常困难),但是链接仍然会工作。幸运的是,考虑到 Firefox 的快速升级周期,数据包边界问题可能太小(无论是受影响的用户还是错误的严重性),不必担心——除非您的网站有大量 Firefox 4 之前的用户。

与 HTML 4 相比有微小变化的其他元素

其他一些元素在 HTML5 中的用法略有变化,或者有了新的属性。让我们看看这些元素和属性,包括<ol>和相关的属性typestartvaluereverse<dl><cite>

  1. 元素和相关的新(和旧)属性

虽然<ol>是 HTML 4 中包含包装在<li>元素中的列表项的相同有序列表,但在 HTML5 中,它现在有了新的reversed属性 http://j.mp/html5-ol)。还有一些从 HTML 4 中掉落的前表示属性已经返回了——<ol>typestart,以及<li>value。和前面提到的表示性元素一样,这些属性实际上具有语义,语义属于 HTML。让我们看看如何依次使用这些属性。

类型属性

一般来说,有序列表的计数器样式是表示性的,应该在 CSS 中处理。但是在一些文档中,它可以是文档的的一部分,意思是,例如法律或技术文档,以散文形式引用非十进制列表项。在这些情况下,我们可以使用type属性在 HTML 中指定列表的样式,如表 4-1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

开始和值属性

start属性让我们设置有序列表的第一个计数器,方便地将一个列表分割成几个<ol>元素,但是从上一个列表停止的地方继续第二个列表的编号。相关值属性允许我们设置一个<li>的值,允许我们手工对一个或多个列表项进行编号。下面的代码展示了如何使用startvalue来继续一个列表,并演示了type:

`

虽然这些是我们的 HTML 工具箱的便利补充,但是添加或删除列表项会使编号显得混乱。因此,您可能希望研究 CSS 生成的内容计数器;阅读大卫·斯托里的《用 CSS 计数器自动编号》。像“1.2.1”这样的嵌套列表计数器也需要它们。


15

颠倒的属性

<ol reversed>是全新的,允许我们创建降序列表,这对于十大列表和火箭发射非常方便。虽然在撰写本文时浏览器对reversed的支持还处于萌芽状态,但我们总是可以使用value来伪装它,它和其他 HTML 3.2 属性一样,仍然被所有浏览器支持。这很方便,因为我们可以结合使用 Modernizr 和 JavaScript polyfill 来轻松添加支持(关于 polyfill 的定义,请参见第二章)。关于这个(和所有这些属性)的更多信息,请参考我们更详细的文章“ol 元素和相关属性:类型、开始、值和反转”([j.mp/ol-attrib](http://j.mp/ol-attrib)<sup>16</sup>)。

元素

在 HTML 4 中,<dl>是定义列表,也是标准化组织中激烈争论的话题。取决于你与谁交谈,它要么仅仅是字典式的定义,要么可能是一个适合所有类型内容的容器:对话、地址,等等。HTML 4 有些松散的描述和不寻常的例子没有帮助。

在 HTML5 中,事情变得更加清晰。最大的变化是现在为名称-值对提供了一个描述列表

dl 元素表示一个由零个或多个名称-值组组成的关联列表(一个描述列表)。…名称-值组可以是术语和定义、元数据主题和值、问题和答案或任何其他名称-值数据组。

生活标准,WHATWG ( [j.mp/html5-dl](http://j.mp/html5-dl)<sup>17</sup>)

我们新的描述列表仍然使用旧的<dt>作为名称,使用<dd>作为值,并且我们仍然可以有多个名称(因此称为“组”)。一个新的警告是每个<dl>只能使用一个<dt>名称,这要求我们将所有相关的<dd>值一起列在相关的<dt> (或一组<dt>),下,而不是重复的名称。

虽然 HTML5 规范对现在的<dl>更加具体,但它实际上有相当广泛的用途。


16

17 [www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dl-element](http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-dl-element)

在字典或词汇表中定义单词

这仍然是对<dl>的完美使用,只要我们用语义上合适的“定义实例”<dfn>元素来表示被定义的单词。

`


   rocket
   外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  
A vehicle that is propelled by the high-speed expulsion of exhaust gases, from
propellants the vehicle carries.

`
[计]元数据

元数据通常由名称和值组成。例如,可以使用<dl>显示一张照片的 EXIF 数据。

`


   Camera
  
Canon EOS 5D Mark II

   Exposure
  
0.01 sec (1/100)

   Aperture
  
f/1.2

`

虽然 HTML 4 规范展示了一个使用<dl>作为对话框的例子,但这不再是一个有效的用法。使用<p>或带有<li><ol>作为容器;如有必要,使用<b>标记发言者姓名。

虽然我们已经展示了一些好的用途和一个不合适的用途,但有些内容可能更难决定。如果你不确定<dl>是否合适,考虑一下<table>(用于更多的语义结构)或者仅仅是<h1> - <h6>(用于包含大量内容的值)是否更适合内容。

<引用>元素

这个元素也是很多争论的主题,也是因为一个模糊的 HTML 4 规范。尽管使用了一些<cite>来引用人(最著名的是 Mark Pilgrim 和 Jeremy Keith),HTML5 规范现在说

cite 元素代表作品的标题。[……]一个人的名字不是一件作品的标题——即使人们称这个人是一件作品——因此,这个要素不得被用来标记人的名字。

生活标准,WHATWG ( [j.mp/html5-cite](http://j.mp/html5-cite)<sup>18</sup>)

规范列出了这些“一件工作”的例子

  • 文章
  • 得分
  • 歌曲
  • 脚本
  • 电影
  • 电视节目
  • 比赛
  • 雕刻
  • 绘画
  • 戏剧制作
  • 歌剧
  • 音乐的
  • 展览
  • 法律案件报告等。

18

使用

以下是引用一本书的例子,有链接和没有链接。

`

While Remy and Bruce did a masterful job on Introducing HTML5, I’m not sure
about that shade of brown.

While Remy and Bruce did a masterful job on ****Introducing HTML5****, I’m not sure about that shade of brown.

`
何时不使用

HTML5 规范没有明确地将网页列为“作品”的例子,添加一个带有<a>的链接就足够了,除非你特别想要一个更学术风格的引用。这也无妨,否则我们将在<引用>中包装每个外部站点的链接。以下是对<blockquote>中一段引文的学术风格引用:

`


  

A person’s name is not the title of a work — even if people call that person a piece of
work

****HTML Living Standard****, WHATWG, retrieved 25 March 2012

`

假设你没有决定坚持 HTML 4 中包含人的<cite>定义,任何名字都可以用<b>来标记。我们建议您考虑使用微数据或微格式在语义上表示人(我们将很快讨论这两者)。此外,当您想要引用某些文本时,要注意不要使用<cite>,因为行内引用应该使用<q>(或者甚至只使用适当的撇号,比如" ")。

新增语义元素

现在让我们来认识一些填补 HTML 中语义空白的新元素:<mark><time>,以及<ruby><rt><rp>三人组。这些将帮助我们从语义上公开一些特定类型的数据,我们到目前为止还没有工具来处理这些数据。

<标记>元素

这个新元素用于指示你特别想要突出显示或引起注意的文本,而不改变其重要性或强调。规格说明听起来相当不具体。

mark 元素表示一个文档中的一串文本,由于其在另一个上下文中的相关性,该文本被标记或突出显示以供参考。

生活标准,WHATWG ( [j.mp/html5-mark](http://j.mp/html5-mark)<sup>19</sup>)

但是,对于某一类内容来说,这正是你一直想要的。为了让事情更清楚,有几个具体的用例。

  • 指示在搜索结果页面中搜索的单词或短语。
  • 指示代码示例中感兴趣的特定代码,如周围文本中讨论的更改。
  • 突出原文中没有强调的引用部分。

突出显示搜索词是我们都可以想象的事情,但我们不会经常这样做,所以让我们看一些代码示例。为了实现相同的格式,我们可以使用下面的 HTML:

<p>While Remy and Bruce did a masterful job on <mark>&lt;cite&gt;</mark>Introducing HTML5<mark>&lt;/cite&gt;</mark>, I’m not sure about that shade of brown.</p>

While Remy and Bruce did a masterful job on **<cite>**Introducing HTML5**</cite>**, I’m not sure about that shade of brown.


19

注意,在表示关联性时,<mark>不同于<em><strong>。这在原文已经包含<em><strong>的引用中非常方便,但是您想要将注意力吸引到特别相关的部分(结果如图图 4-9 所示)。

`


  

Dogs are the best! They are obviously much cooler than monkeys,
even if the first animal in space was a monkey.

` ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Fvkdoc-html-css-zh%2Fraw%2Fmaster%2Fdocs%2Fbegin-h5c3-web-evo%2Fimg%2F9781430228745_Fig04-09.jpg&pos_id=img-XudUFaPn-1723651960864)

图 4-9 。包含<em><strong><mark>的引用文本的渲染示例

像往常一样,考虑是否有更合适的语义元素。除了<strong><em><b><i>之外,使用没有href属性的<a>来表示导航中的当前页面(活动标签页),使用<a>上的一个类来代替永久链接。不是你每天都需要的东西,但现在你知道如何使用它了。

红宝石标注有<红宝石>、< rt >和< rp >

拼音文本是一些基本文本的简短注释。它通常用于在汉语、日语和朝鲜语(CJK)的汉字或日本汉字的语音脚本中提供发音指导。它是以一个旧的印刷术语命名的,指的是 5.5 磅的极小尺寸。

ruby 元素允许用 ruby 注释标记一段或多段语法内容。

生活标准,WHATWG ( [j.mp/html5-ruby](http://j.mp/html5-ruby)<sup>20</sup>)


20 [www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element](http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element)

顾名思义,拼音文本很小,默认情况下在水平文本中显示在基础文本的上方,在垂直文本中显示在右侧。不支持<ruby>的浏览器将拼音文本放在基本文本之后。

这些是在 HTML5 中创建拼音文本时使用的元素:

  • <ruby>是一个内联元素,包含带有拼音注释和可选拼音括号的基本文本。
  • <rt>是拼音文本,位于它定义的基本文本之后。
  • <rp>是拼音括号,一个用于将左括号和右括号括在<rt>(拼音文本)周围的元素。这些是为不支持 ruby 文本的用户代理准备的,所以它在内联显示时有意义。支持<ruby>的浏览器通过{display:none;}隐藏<rp>

如果你从未见过 ruby 的实际操作,你可能会想知道我在说什么,所以图 4-10 显示了一个来自日本漫画的例子。微小的字符是汉字左边的红宝石注释,向读者显示正确的发音。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-10 。井上雄彦的漫画流浪汉中的红宝石文字(日语称为 furigana

正如国际化特性通常所做的那样,浏览器支持是稀疏的。出乎意料的是,Internet Explorer 从 IE5 开始就支持<ruby>——比实际的 2001 W3C Ruby 注释规范早了三年!虽然这个规范被合并到 XHTML 1.1 中,但是没有浏览器实现过它。

HTML5 中的<ruby>基于 IE 实现的逆向工程,比旧的 Ruby 注释规范更简单。WebKit 浏览器在 2010 年初增加了 HTML5 <ruby>支持,但是 Firefox 和 Opera 还没有在本地实现<ruby>。在 CSS 文本布局模块级别 3 中也有支持 ruby 的 CSS3 属性,但是这些属性的实现都很差。幸运的是,有一个基于 CSS 2.1 的 polyfill 和一个通过 Modernizr 检测支持的社区插件。首先,在展示 polyfill 之前,我们将看看如何在英语中使用它。

英语使用

不是每个人都使用东亚语言,但是任何简短的注释(理论上)都是适用的,并且不需要多填充。虽然英语通常没有发音指导,但字典中会使用语音注释。下面的代码通过在基本文本后内联显示拼音文本,将拼音文本用于词典定义。我们使用了<dfn>元素来表示这是术语的定义实例(参见图 4-11 中的结果)。

<style> /* display rt and rp elements inline */   rt, rp {display: inline; font-size: 100%;}   dfn {font-weight: bold; font-style: normal;} </style> <ruby><dfn>cromulent</dfn> <rp>(</rp><rt>crôm-yü-l**ə**nt</rt><rp>)</rp></ruby> 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-11 。通过在基本文本后内联显示拼音文本,将拼音文本用于词典定义。

我们明确地将<ruby>视为语音注释的语义(也是有价值的),就像<abbr>元素的title属性提供关于潜在混淆内容的额外信息一样。然而,在这种用法之外,<ruby>可以被看作是一种表象上的欺骗。与<q>非常相似,当默认显示与纯文本相同时,使用<ruby>的额外代码可能不合理。

<ruby><rt><rp>元素是有效的 HTML5,即使它们没有得到广泛支持,它们也会默认显示*,就好像它们是不支持的浏览器中的* <span> s 。结合聚合填充支持的能力,我们说如果您确实需要<ruby>的语义,比如 CJK 注音,就使用它们*(见下一节)。对于非语音注释,考虑使用<abbr title="">通过鼠标悬停在缩写或首字母缩略词上给出扩展读数,除非默认显示读数很重要。考虑一下<small>对内容的措辞级别的附带评论,比如法律术语。*

多填充支持东亚语言

由于<ruby>的 polyfill 只需要 Modernizr 和 CSS,我们来看看如何为东亚文本实现它,作为 poly fill 的一个例子(这将让您知道如何在其他真正需要它的注释的情况下使用它)。首先,我们需要定制一个包含“elem-ruby”附加组件的 Modernizr 脚本来检测<ruby>支持。你可以通过去[www.modernizr.com](http://www.modernizr.com)并选择“生产:配置你的构建”来得到它在配置窗口中,确保您至少选择了

  • 额外的现代负荷
  • 扩展性外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Modernizr.addTest
  • 社区附加组件外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 elem-ruby

在样式表引用之后,将此脚本添加到页面的<head>中:

`

             Ruby test          ****      …`

成功添加脚本后,使用浏览器的开发工具检查页面,会发现 Modernizr 已经将<html>起始标签更新为<html lang="en" **class="js ruby"**>以支持浏览器,或者更新为<html lang="en" **class="js no-ruby"**>以支持非支持浏览器(假设 JavaScript 没有被禁用)。我们现在可以在样式表中使用no-ruby类来添加 CSS polyfill。我们将使用的 CSS 基于 Zoltan·拉克([j.mp/ruby-polyfill](http://j.mp/ruby-polyfill)<sup>21</sup>)的“使用 CSS 的跨浏览器 HTML5 Ruby 注释”。

ruby {ruby-align: center;} .no-ruby ruby {   display: inline-table;   text-align: center;   border-collapse: collapse;   border: none;   vertical-align: middle; } .no-ruby rp {display: none;} .no-ruby rt {   display: table-header-group;   font-size: 0.5em;   line-height: 1.2em;   white-space: nowrap; } .no-ruby rt + rt {   display: table-row;   border-bottom: hidden; }


21

关于这将如何显示的示例,无论有无聚合填充(或有本地支持),参见图 4-12 (无<rp>)和图 4-13 (使用<rp>)。别管日本人是什么意思;请记住,<rt>中的简单字符是它们前面的复杂字符的 ruby 读数。

图 4-12 显示了 furigana 中的一个系列,带有代码示例、一个支持或多填充的浏览器渲染,以及一个不支持的浏览器渲染(例如,在 Opera 中没有多填充或有多填充但禁用了 JavaScript)。ruby 注释“内联”时缺少括号,这使得最后一个例子难以阅读。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-12 。用<ruby>表示果壳动漫中鬼的日文名字发音

图 4-13 添加了<rp>元素,这是在不支持的浏览器中为拼音文本提供的 HTML 级回退,即使在没有 polyfill 的不支持的浏览器中也能正常降级。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-13 。相同的例子,但是在<rp>元素中用括号将<rt>文本括起来

<时间>元素

另一个新元素是<time>,它最终为我们提供了一种官方的机器可读的方式来表示时间、日期和持续时间数据。

time 元素表示其内容,以及 datetime 属性中这些内容的机器可读形式。内容的种类仅限于各种日期、时间、时区偏移量和持续时间。

生活标准,WHATWG ( [j.mp/html5-time](http://j.mp/html5-time)<sup>22</sup>)

日期或时间信息可以是元素的内容,但通常您会希望使用更自然的表达方式(例如“三天前”)。<time>为此使用属性datetime。表 4-2 说明了允许的日期和时间类型(是 ISO8601 的子集)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本地日期时间相对于作者是本地的。对于全球日期时间时区,Z表示协调世界时,即 UTC。它有时被称为祖鲁时间(因此称为“Z”),相当于时区+00:00,更普遍的说法是 GMT。


22

23

何时不使用

<time>使用基于公历的日期,这只能追溯到 0000 年,所以不可能对这之前的日期使用<time>(考虑微数据或 RDFa 代替)。此外,历史爱好者需要将儒略历日期转换为格里高利日期作为datetime值,如下所示:

Gaius Julius Caesar Augustus was born 23 September 63 BC<!-- we can’t use <time> for this date -->, and died <time datetime="0014-07-17">19 August AD 14</time> (Julian calendar).

<time>元素不能用于日期范围、不能转换成秒的持续时间(不包括月和年),或者类似“发射前几周”或“莱卡出生于 1954 年左右”的近似时间

<time>自从最初添加到规范中后,已经经历了一些变化。一个积极的变化是该元素现在可以表示没有年份的日期、星期、时区偏移量和持续时间,这在以前是没有的。这使得它能够表示<input>元素的新的日期相关类型(在第六章中涉及)。

另一个变化是删除了pubdate属性,这是一个布尔属性,用于指示这个日期时间值是最近的祖先<article>元素的发布日期,如果没有,则是整个文档的发布日期。在撰写本文时,这个属性已经从 HTML5 规范中删除,建议的替换是将<time>元素与 hAtom 微格式词汇表或 Schema.org 文章微数据词汇表一起使用。微格式和微数据将在本章后面介绍。

扩展 HTML5

虽然 HTML5 有一堆很棒的新语义元素,如<article><time>,但有时就是没有一个元素有正确的语义。我们想要的是扩展我们已有的东西的方法——添加浏览器、脚本或机器人可以使用的机器可读数据。这可以从添加用于 JavaScript 的元数据到为 HTML5 元素添加额外的语义,再到添加内容中没有的全新语义数据。

HTML 4 有五种基本的扩展方式。

  • <meta>元素
  • classrelrevprofil e 属性

revprofile已经半途而废(由于几乎没有人正确使用rev,也几乎没有人真正使用profile ), <meta>classrel仍然留在 HTML5 中。事实上,<meta>现在有了规范定义的名称([j.mp/html5-meta-name](http://j.mp/html5-meta-name)<sup>24</sup>)和提交新名称值的方法,而rel有了在 HTML5 规范([j.mp/html5-rel-type](http://j.mp/html5-rel-type)<sup>25</sup>)中定义的几个新链接类型()和提交更多链接的方法。更好的是,ARIA 的角色和aria-*属性(我们在第三章的结尾遇到过,它们不是 HTML 4 的一部分)可以用于在 HTML5 中添加与可访问性相关的角色(“附加”可访问性),HTML5 验证器可以检查 HTML5+ARIA。


24

除此之外,还有几种扩展 HTML5 的新方法,包括:

  • <data>元素及其val属性
  • 自定义数据属性(data-*)
  • 微观数据
  • 网页摘要和结构化标记

虽然我们不会讨论 RDFa,但我们将快速浏览一下微格式,微格式是一种使用约定的class属性值添加语义的方法,也是创建 HTML5 微数据的先驱。让我们先来看看新产生的<data>元素,它基本上是我们刚刚遇到的<time>元素的一般化版本。

<数据>元素

<time>元素为我们提供了一种以机器可读的方式表示日期、时间和持续时间的简单方法,但是在显示人类可读的内容时,我们可能还想让许多其他类型的数据成为机器可读的。为此引入了具有value属性的<data>元素。

数据元素表示其内容,以及那些内容在value属性中的机器可读形式。

生活标准,WHATWG ( [j.mp/html5-data](http://j.mp/html5-data)<sup>26</sup>)


25 [www.whatwg.org/specs/web-apps/current-work/multipage/links.html#linkTypes](http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#linkTypes)

26 [www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-data-element](http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-data-element)

它非常适合使用微数据和(潜在的)微格式,并允许我们将脚本数据与人类可读的对等物关联起来。唯一的限制是<data> 必须具有value属性,该属性必须是元素内容的表示。以下代码显示了这是如何工作的:

The Kármán Line is <data value="100km">62 miles</data> above the Earth’s sea level, and defines the boundry between the atmosphere and outer space.

自定义数据属性(data-*)

例如,您可能需要将值存储在 HTML 中供 JavaScript 使用。最好避免隐藏元数据,而是使用像<time><data>这样的元素将机器可读数据与页面内容联系起来。然而,有时有一种方法可以将脚本的数据附加到任何元素上,这是非常方便的。HTML5 没有滥用像class这样的其他全局属性,而是为这种用途引入了自定义数据属性(“data-*”)。“data-*”名称来自这个全局属性“data-”加上您想要使用的名称。

自定义数据属性旨在存储页面或应用专用的自定义数据,对于这些数据没有更合适的属性或元素。

生活标准,WHATWG ( [j.mp/html5-data-](http://j.mp/html5-data-)<sup>27</sup>)

一个使用的例子(我们将在第九章中更详细地介绍)是用于响应图像,你默认显示小图像,然后使用 JavaScript 在大屏幕设备上换成大图像。我们可以使用data-*直接在<img>元素中存储大图像。

<img src="picture.small.jpg" **data-fullsrc="picture.large.jpg"**>

然后,一个脚本可以将其更新为

<img **src="picture.large.jpg"** data-smlsrc="picture.small.jpg">

在合适的设备上。只要记住data-*是针对你自己的脚本,不适合任何你希望外部脚本使用的数据。有关更多信息,包括如何在 JavaScript 中访问、创建和更改data-* 值,请阅读 Chris Bewick ( [j.mp/html5-data2](http://j.mp/html5-data2)<sup>28</sup>)的“HTML5 自定义数据属性(data-*)”。


27 [www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes](http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes)

微格式

微格式是用额外的机器可读的语义扩展 HTML 的一种简单方式,首先是为人类设计的,其次是为机器设计的。它们是从普通的旧式语义 HTML (POSH)编码模式发展而来,用于 HTML 4 和 XHTML 1,并通过约定的classrelrevprofile语法、编码模式和嵌套工作。机器可读部分意味着理解所用微格式词汇表的机器人或脚本可以理解微格式添加到标记数据中的额外语义。每种微格式都用于特定类型的数据,通常基于现有的数据格式,如 vcard(地址簿数据;RFC2426)和 icalendar(日历数据;RFC2445),或者公共编码模式(web 的“铺路”)。微格式易于实现,因此许多服务都提供 hCard 格式的概要信息;因此,即使您以前从未使用过微格式,您也可能已经有了微格式的概要文件。您可以在微格式 wiki ( [microformats.org/wiki](http://microformats.org/wiki))上找到更多关于许多微格式和创建新微格式的过程的信息。

微格式简介

以防您以前从未使用过它们,我将简要介绍一些简单的微格式——希望如此简单,您会被鼓励立即尝试它们。

使用 rel-license 获取许可信息

添加许可信息是一个相当常见的活动,虽然我们可以很容易地添加到 Creative Commons 或另一个许可的链接,但有人必须阅读它才能理解内容的许可。

<small>This article is licensed under a <a href="http://creativecommons.org/licenses/by-nc- sa/2.0/">Creative Commons Attribution Non-commercial Share-alike (By-<abbr>NC</abbr>- <abbr>SA</abbr>) license</a>.</small>

如果这些信息是机器可读的,它将有助于消费者搜索具有特定许可的内容。通过使用rel-license微格式将rel="license"添加到链接中(表明它是页面主要内容的许可证),我们可以做到这一点。


28 [html5doctor.com/html5-custom-data-attributes](http://html5doctor.com/html5-custom-data-attributes)

<small>This article is licensed under a <a **rel="license"** href="http://creativecommons.org/licenses/by-nc-sa/2.0/">Creative Commons Attribution Non- commercial Share-alike (By-<abbr>NC</abbr>-<abbr>SA</abbr>) license</a>.</small>

这可能太容易了,你甚至没有意识到你已经对链接进行了微格式化。谷歌使用这些数据来允许通过许可证进行搜索,如图 4-14 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-14 。谷歌高级搜索选项中的使用权下拉菜单

这个基本的微格式已经成为 HTML5 的一部分,作为链接类型之一,作为一个rel=""值添加到一个<a><link><area>元素([j.mp/html5-rel-type](http://j.mp/html5-rel-type)<sup>29</sup>)。

使用 XHTML 朋友网络(XFN)

也许我们应该称之为可扩展的朋友网络:-)这是一种指定你与人们关系的方式——从“相识”到“爱人”——在他们主页的链接上使用rel属性。然而,有三个主要的价值。

  • 你知道如何联系的人。
  • rel="me":允许您认领您的各种网站,包括您在社交网络上的账户。
  • 当前文章作者的链接,例如他们的网站或个人资料页面(这是 HTML5 规范中三种链接类型中唯一的一种)。

我们可以使用最后两个来证明我们的身份在线只使用链接。例如,如果你卑微的作者有一个网站或个人资料页面,他可以添加一个链接到我的 Twitter 账户。


29 [www.whatwg.org/specs/web-apps/current-work/multipage/links.html#linkTypes](http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#linkTypes)

<p>Oli Studholme — <a href="https://twitter.com/boblet">follow me on Twitter (@boblet)</a></p>

虽然一个人可以推断出@boblet是我的 Twitter 用户名,但是通过添加rel="me",我们可以用一种机器可读的方式来陈述这种关系。

<p>Oli Studholme — <a **rel="me"** href="https://twitter.com/boblet">follow me on Twitter (@boblet)</a></p>

这需要在这个人自己的个人资料页面上,并在他们的 Twitter 个人资料上添加相同的个人资料页面 URL,才能真正发挥作用。但通过这样做,一个理解 XFN 的社交网络应用可以确认谁是@boblet的,检查 Twitter 上的朋友,检查这些人是否已经注册,然后允许他一键关注所有人——这就容易多了。

谷歌还将允许你通过结合使用rel="me"rel="author"来证明文章的作者身份(只要你有 Google+个人资料或谷歌个人资料)。有几种方法可以做到这一点,所以我们会让你参考谷歌关于证明作者身份的文档([j.mp/google-author](http://j.mp/google-author)<sup>30</sup>),如果你使用 WordPress,请参见 Joost de Valk 的文章“rel="author "和 rel = " me " in WP and other platforms”([j.mp/wp-rel-me](http://j.mp/wp-rel-me)<sup>31</sup>)。这样做可以改变搜索结果的显示方式,例如在搜索结果中将您的个人资料图片放在您撰写的文章旁边。

Rel-license和 XFN 是简单的基于rel的微格式,但是即使简单,你也能看到这种机器可读的东西的潜在力量。现在让我们看看如何使用微格式来保存联系信息。

使用 hCard 获取联系信息

几乎每个网站都有一个“关于”页面,上面有一些联系方式。

<p>By Oli Studholme — <a href="http://oli.jp/">http://oli.jp</a>, or <a href="http://twitter.com/boblet">follow me on Twitter (@boblet)</a>.</p>

不幸的是,将某人的联系信息添加到您的电话或地址簿通常需要大量的复制和粘贴。如果数据是机器可读的,我们可以使用工具导入它。让我们将 hCard 微格式添加到以下代码中:

<p **class="vcard"**>By **<span class="fn">**Oli Studholme**</span>** — <a **class="url"** href="http://oli.jp/">http://oli.jp</a>, or <a **class="url"** href="http://twitter.com/boblet">follow me on Twitter (@**<span** **class="nickname">**boblet**</span>**)</a>.</p>


30 [support.google.com/webmasters/bin/answer.py?hl=en&answer=1229920](http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1229920)

31 [yoast.com/wordpress-rel-author-rel-me](http://yoast.com/wordpress-rel-author-rel-me)

我们添加的类别如下:

  • 包含的<p>元素上的vcard,这表明这里有微格式化的 hCard 数据。
  • fn,代表全名。
  • url访问相关主页。
  • 为了,嗯,一个绰号。

因为我们只是添加类(以及偶尔添加类的<span>元素),除非我们也开始添加 CSS 样式,否则我们的内容的外观或行为不会有任何改变。如果我们需要样式化这些信息,我们已经添加了一些可以使用的类。这是一个非常简单的例子,但是 hCard 有深度。我们可以标记各种与联系人相关的数据,比如地址、公司信息,甚至是个人资料照片。例如,默认情况下,hCard 将fn中的两个单词映射为“名”和“姓”(这在英语中很常见)。但是对于一种不同顺序的语言,或者中间名和头衔等等,我们可以(嗯,必须)显式地陈述这些数据。以下代码显示了对先前 hCard 代码的更新,只是这一次使用了日文名称,并显式显示了family-namegiven-name hCard 类:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么这样做有什么好处呢?嗯,有几个工具可以将这种 hCard 微格式数据转换成 vcard 文件,我们可以下载并自动添加到我们的地址簿中,例如图 4-15 所示的 Firefox 的 Operator 插件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-15 。Firefox 插件运营商可以将 hCard 格式的内容保存为 vcard,这是大多数地址簿和电子邮件程序都可以导入的格式

谷歌的 Rich Snippets(shcema.org 的前身,我们将在本章后面的微数据部分介绍),如图 4-16 所示,以及雅虎的 SearchMonkey,这对于任何公司网站上的联系信息都非常有用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-16 。Google 丰富的代码片段测试工具

在 HTML5 中使用微格式

微格式是在 HTML5 之前开发的,有一些使用了已经被放弃的属性(revprofile)。然而,大多数微格式只使用class和/或rel,所以它们在 HTML5 中完全没问题。但是因为微格式是在 HTML5 之前开发的,它们(还)没有利用新的<time><data>元素。一些处理或生成微格式的工具也不支持 HTML5。虽然微格式可能是用预定义语义扩展 HTML5 的最简单的方法,但是让我们将它们与新的“本地”HTML5 扩展方法微数据进行比较。

微数据:HTML5 的语义层

微数据是一种新的轻量级语义元语法,使用嵌套的数据名称-值对,通常基于页面的内容。这是添加额外语义信息和扩展 HTML5 的全新方式。

有时,希望用特定的机器可读标签来注释内容,例如,允许通用脚本提供针对页面定制的服务,或者使来自多个合作作者的内容能够由单个脚本以一致的方式处理。[…]微数据允许将名称-值对的嵌套组与现有内容并行添加到文档中。

([j.mp/html5-microdata](http://j.mp/html5-microdata)<sup>32</sup>)

注意:微数据一直有些争议,所以它在 W3C 是一个单独的规范,但仍然是 WHATWG HTML5 规范的一部分。保持冷静,坚持下去。

微数据和微格式之间的主要区别是

  • 微数据使用新的全局属性,而不是“重载”属性。
  • 微数据可以在不知道所用词汇的情况下被机器解析。
  • 虽然我们建议标记作为页面内容一部分的值,但页面内容和任何微数据项之间没有内在联系。
微数据语法

微数据引入了五个新的全局属性。

  • Itemscope:定义一组名值对,称为项。
  • itemprop="property-name":给微数据项添加一个属性。属性的名称可以是单词或 URL,值是具有此属性的元素的“内容”:
  • 对于大多数元素,该值是元素的文本内容(不包括任何 HTML 标记)。
  • 对于具有 URL 属性的元素,值是 URL ( <img src=""><a href=""><object data="">等)。
  • 对于<time>元素,该值是datetime=""属性。
  • 对于<data>元素,该值是value=""属性。
  • 对于<meta itemprop="" content="">,该值是content=""属性。
  • itemref="":通过引用id属性,允许微数据项包含非继承属性
  • itemtype="":通过在与itemscope相同的元素上使用itemtype=""来定义项目的类型(包含一个充当唯一词汇名称的 URL)。
  • itemid="":允许微数据项与词汇表指定的唯一标识符相关联,例如一本书的 ISBN 号。在与项目的itemscopeitemtype相同的元素上使用itemid

32

让我们研究一下这些新属性,看看如何在实践中使用微数据。

项目范围项目属性

itemscope的存在使得<p>元素成为微数据项。派生元素上的属性itemprop定义了该项目的属性name,并将其与值Salter Cane(<span>的内容)相关联。一个项目必须至少有一个itemprop才有效。

<p **itemscope**>I’m going to the <span **itemprop="name"**>Salter Cane</span> gig next week. Excited!</p>

itemprop名称可以是单词或 URL 字符串。使用 URL 使得名称成为全球唯一的。如果使用单词,最好通过词汇表使用定义好的单词,这也使名字独一无二。我们将在“类型化项和全局唯一名称”一节中对此进行更详细的介绍。

属性中的 itemprop

对于某些元素来说,itemprop的值来自元素的属性。

<p itemscope>I’m going to the <**a itemprop="url" href="http://www.saltercane.com/"**>Salter Cane</a> gig <**time itemprop="date" datetime="2012-08-18"**>next week </time>. Excited!</p>

这定义了一个具有属性urldate的项目,分别具有值[www.saltercane.com/](http://www.saltercane.com/)2012-08-18

注意,链接的itemprop="url"值是[www.saltercane.com/](http://www.saltercane.com/),而不是元素的“Salter Cane”文本内容。在微数据中,以下元素以值的形式提供它们的 URL:

  • <a href="">
  • <area href="">
  • <audio src="">
  • <embed src="">
  • <iframe src="">
  • <img src="">
  • <link href="">
  • <object data="">
  • <source src="">
  • <track src="">
  • <video src="">

注意:不使用的包含 URL 属性的 HTML5 元素是

*<base href="">* *<script src="">* *<input src="">*

要使用文本<a href="">作为属性值,我们需要添加一个额外的itemprop

<p itemscope>I'm going to the <a itemprop="url" href="http://www.saltercane.com/">**<span** **itemprop="name">**Salter Cane**</span>**</a> gig <time itemprop="date" datetime="2012-08-18">next week</time>. They’re gonna rawk!</p>

这定义了一个有三个属性的项目:url[www.saltercane.com/](http://www.saltercane.com/),nameSalter Cane,date2012-08-18

嵌套项目

itemscope添加到带有itemprop的元素中,使属性成为嵌套项。

<p itemscope>The <span itemprop="name">Salter Cane</span> drummer is <span **itemprop**="members" **itemscope**><span itemprop="name">Jamie Freeman</span>.</span></p>

这定义了一个具有两个属性的项目:namemembersnameSalter Cane,members是包含属性name和值Jamie Freeman的嵌套项。注意members没有文本值。

不属于其他项目的项目(即任何带有itemscope而不是itemprop的项目)被称为顶级微数据项。微数据 API 只返回顶级微数据项及其属性(包括嵌套项)。

多重属性

项目可以有多个具有相同名称和不同值的属性。

<span itemprop="members" itemscope>The band members are <span **itemprop="name"**>Chris Askew</span>, <span **itemprop="name"**>Jeremy Keith</span>, <span **itemprop="name"**>Jessica Spengler</span> and <span **itemprop="name"**>Jamie Freeman</span>.</span>

这用四个值定义了属性名:Chris Askew、Jeremy Keith、Jessica Spengler 和 Jamie Freeman。

一个元素也可以有多个属性值相同的属性(用空格分隔的多个itemprop=""名)。

<p itemscope><span **itemprop="guitar vocals"**>Chris Askew</span> is so dreamy.</p>

这定义了属性guitarvocals,它们的值都是Chris Askew

页内参考文献

项目可以通过属性itemref=""使用非后代属性(不是itemscope元素的子元素的名称-值对)。使用它可以在页面上的其他位置列出属性或嵌套项的 id。

`<p itemscope itemref=“salter-cane-members”>I’m going to the Salter Cane gig . Excited!


Salter Cane are

这定义了属性urlnamedate,并引用 ID salter-cane-members,它包含具有四个name属性的项目members,每个属性具有不同的值。我们也可以利用这一点来保持我们的代码干燥(不要重复自己),例如,通过使用itemref在一个页面的同一个位置包含几个事件,节省我们为每个事件重复它。

使用通过属性添加内容

如果您想要添加的文本还不是页面内容的一部分,您可以使用content属性(<meta itemprop="" content="">)将其添加到项目中。

<p itemscope><span itemprop="name" itemscope>Jessica Spengler**<meta itemprop="likes"** **content="Mameshiba">**</span>’s fans are always really raucous.</p>

不幸的是,一些不支持的浏览器将<meta>移到了<head>。优雅的解决方法是通过itemref使用页面内引用。

<p itemscope><span itemprop="name" itemscope **itemref="meta-likes"**>Jessica Spengler<**meta** **id="meta-likes"** itemprop="likes" content="Mameshiba"></span>'s fans are always really raucous.</p>

这两个代码片段都用值Jessica Spengler定义了属性name,用值Mameshiba定义了嵌套属性likes

注意:微数据和页面内容没有关系。通过<meta>添加所有微数据相当于使用页面内容添加元数据——只是不推荐。

虽然微数据最适合注释现有内容,但通过使用基于<meta>的值或隐藏值,微数据不必与页面内容绑定。然而,一般来说,向页面添加隐藏内容是一个坏主意,因为很容易忘记它,不能保持它的最新状态。如果信息对某些用户有用,就把它添加到页面内容中。如果不方便在条目中添加内容,可以考虑把它放在一个<footer>中,并包含一个页面内引用。

具有 itemid 的全局标识符

有时,一个条目可以用一个唯一的标识符来标识,比如一本书可以用它的 ISBN 号来标识。这可以通过属性itemid=""使用全局标识符在微数据中完成。将该属性添加到同时具有itemscopeitemtype=""的元素中。

`


  

`

这将定义一个包含由 ISBN 号 1-59059-533-5、标识的书的信息的条目,只要[vocab.example.com/book](http://vocab.example.com/book)词汇表定义这个全局标识符。

类型化项(itemtype)和全局唯一名称

我们可以通过在带有itemscope的元素上使用属性itemtype=""给一个项目赋予一个类型来将它与微数据词汇表联系起来。itemtype=""值是一个代表微数据词汇表的 URL。注意,这个 URL 只是一个文本字符串,充当惟一的词汇标识符;它实际上不需要任何内容。这样做之后,我们可以使用词汇表中的名称作为itemprop名称来应用词汇表定义的语义。

<p **itemscope itemtype="http://schema.org/MusicGroup"**>I went to hear <a itemprop="url" href="http://saltercane.com/"><span itemprop="name">Salter Cane</span></a> last night. They were great!</p>

这个例子根据[schema.org/MusicGroup](http://schema.org/MusicGroup)词汇表(MusicGroup是 schema.org 上一种特殊的组织词汇表)定义了值为[saltercane.com/](http://saltercane.com/)的属性 URL 和值为 Salter Cane 的属性 name。

或者,如果您使用 URL 作为itemprop名称,就没有必要使用itemtype,因为名称中已经包含了词汇信息。这些被称为全球唯一的名字。虽然基于词汇表的名称必须在键入的项目中使用,以具有词汇表定义的含义,但是您可以在任何地方使用 URL itemprop名称。让我们用基于 URL 的名称重写前面的例子。

<p itemscope>I went to hear <a **itemprop="http://schema.org/MusicGroup/url"** href="http://saltercane.com/"><span **itemprop="http://schema.org/MusicGroup/name"**>Salter Cane</span></a> last night. They were great!</p>

这允许您在同一个代码片段中使用多个词汇表,即使它们使用相同的属性名。

行动中的微数据

所以现在我们知道了如何,但是为什么我们会想要使用微数据呢?一个用途是添加额外的语义或数据,我们可以通过 JavaScript 以类似于定制数据属性(data-*)等的方式来操作它们。然而,如果我们通过itemtype或基于 URL 的itemprop名称来使用词汇表,微数据会变得更加强大。微数据是机器可读的,不需要知道词汇表,一旦我们使用了词汇表,其他人就可以知道我们的属性是什么意思。这使得数据有了自己的生命。说什么?实际上,使用词汇表使微数据成为内容的轻量级 API。

现在我们可以开始临时编造自己的名字,但这很大程度上限制了其他人使用我们的数据。通过使用词汇表并遵循其规则,其他人也可以使用我们的数据。使用词汇表是个好主意,那么我们去哪里找呢?

使用 schema.org 词汇

必应、谷歌和雅虎合作开发了一套名为 schema.org 的微数据词汇表。通过使用这些词汇表,我们可以用这些搜索引擎能够理解的方式在内容中传达语义信息。虽然使用这些词汇添加语义不会影响您的搜索排名,但包含的数据可能会显示在搜索结果中。schema.org 提供的主要词汇有

  • 创意作品:创意作品,书籍,电影,音乐录音,食谱,电视剧…
  • 嵌入的非文本对象:音频对象、图像对象、视频对象
  • 事件
  • 组织
  • 地方,本地商业,餐馆…
  • 产品,报价,总报价
  • 审查,汇总评级

它们是 Google 早期 Rich Snippets 词汇表的跨搜索引擎继承者。不像 Rich Snippets,它也有微格式和 RDFa 版本,schema.org 词汇表目前有争议地只支持微数据。

下面是一个基本的 HTML 代码片段。

`


  

Designing in the browser by Divya Manian


  

- at the RACV City Club, 501 Bourke St, Melbourne, Australia


  

The new technologies available in HTML5 already allow you to create prototypes quickly in
the browser. Learn how to create a prototype from start to finish using these new technologies
while taking advantage of quick prototyping tools.

`

让我们给它添加一些微数据精灵粉。为事件、演讲者和位置添加微数据属性(加上偶尔添加的<span>),而不改变 HTML 的显示方式。

`<section itemscope itemtype=“http://schema.org/Event”>
  

<a itemprop=“url” href=“http://code12melb.webdirections.org/”><span
itemprop=“name”>Designing in the browser by <span itemprop=“performers” itemscope
itemtype=“http://schema.org/Person”><a itemprop=“url” href=“http://nimbupani.com/”><span
itemprop=“name”>Divya Manian


  

<time itemprop=“startDate” datetime=“2012-05-23T16:20:00+10:00”>May 23rd 4:20pm-
<time itemprop=“endDate” datetime=“2012-05-23T17:15:00+10:00”>5:15pm at the <span
itemprop=“location” itemscope itemtype=“http://schema.org/Organization”><a itemprop=“url”
href=“http://j.mp/HdvMwM”>RACV City Club****


  <p itemprop=“description”>The new technologies available in HTML5 already allow you to
create prototypes quickly in the browser. Learn how to create a prototype from start to finish
using these new technologies while taking advantage of quick prototyping tools. `

虽然这些内容的显示方式没有任何变化,但有了这些微数据项,以下信息现在是机器可读的(词汇表将这一个演讲视为一个事件,或者更准确地说,是一次会议的子事件,尽管为了简单起见,我们将把它省略掉):

  • 演讲名称(name)
  • 语音 URL(<a>上的url)
  • 发言人(performers),其代表为
    • 发言者姓名(name)
    • 演讲者的关联 URL ( url)
  • 演讲开始和结束时间(startDateendDate)
  • 语音位置(location),由
    • 地名(名称)
    • 放置 URL (url 在
  • 言语描述(description)

注意:虽然这些itemprops可能是不言自明的,但是您可以在eventpersonplace vocabulary页面上看到每个itemprop的含义描述。

这将给出以下机器可读的输出:

:type: http://schema.org/Event :properties:   url:   - http://code12melb.webdirections.org/   name:   - Designing in the browser   performers:   - :type: http://schema.org/Person     :properties:       url:       - http://nimbupani.com/       name:       - Divya Manian   startDate:   - Wed, 23 May 2012 16:20:00 +1000   endDate:   - Wed, 23 May 2012 17:15:00 +1000   location:   - :type: http://schema.org/Place     :properties:       url:       - http://j.mp/HdvMwM       name:       - RACV City Club   description:   - The new technologies available in HTML5 already allow you to create prototypes quickly in the browser. Learn how to create a prototype from start to finish using these new technologies while taking advantage of quick prototyping tools.

Google 提供了一个丰富的 Snippet 测试工具,显示了它可以从页面上的微数据(加上任何可识别的微格式和 RDFa)中提取什么数据(见图 4-17 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 4-17。**拉拉拉

然后,搜索引擎可以在显示搜索结果时使用这些额外的数据,例如在结果中添加日期和位置,所有这些都不需要那些讨厌的自然语言解释器(也称为人类)。

任何以前使用过微格式的人都会注意到这些词汇表看起来非常类似于 hCard 和 hCalendar,尽管有一些名称上的变化(例如,Calendar 的class="dtstart"变成了itemprop="startDate"))。

虽然 schema.org 词汇表是所有搜索引擎都承诺支持的,但是您可以自己扩展这些词汇表。最安全的方法是通过

  • 基于维基百科的产品或服务的产品类型本体([www.productontology.org](http://www.productontology.org))。
  • 电子商务的 GoodRelations 词汇术语([j.mp/goodrel](http://j.mp/goodrel)<sup>33</sup>)。
  • 使用 schema.org 电子邮件列表,合作开发你自己的 schema.org 词汇扩展。请务必先阅读“创造自己的词汇”部分。
工具和浏览器支持

使用正确的工具,我们可以使用这些数据,完成其显式语义,例如,将这个事件直接添加到日历中——如果您打算去,这非常方便!随着 schema.org 的发布,微数据工具开始出现,但在地面上仍然有些单薄。但是,以下库是可用的:

  • Philip jgenstedt([j.mp/live-md](http://j.mp/live-md)<sup>35</sup>)的实时微数据和相关微数据
  • Alex Holt 的 PHP 微数据解析器([j.mp/php-md](http://j.mp/php-md)<sup>36</sup>)
  • 蓝雨青,一个 Ruby 的微数据解析器/提取器库和命令行工具
  • 微观数据-按术语排列的 JS([j.mp/md-js](http://j.mp/md-js)<sup>38</sup>)

33

34

35

36

37 [lawrencewoodman.github.com/mida](http://lawrencewoodman.github.com/mida)

Live 微数据将微数据转换成 JSON。PHP 微数据库允许您解析 HTML 文件中的微数据,返回 JSON 或 PHP 数组。蓝雨青允许你提取微数据作为 JSON,然后搜索或检查物品。它支持定义词汇,并包括 schema.org 词汇。您甚至可以从命令行使用它。微数据-JS 是微数据的聚合填充。Validator.nu ( [validator.nu](http://validator.nu))也会验证你对微数据的使用,但不会验证它是否符合某个词汇表。正如我们已经看到的,Google Rich Snippets 测试工具验证微数据,如果你使用 schema.org 词汇表,应该显示这些数据如何被整合到搜索结果中。

微数据规范描述了微数据 DOM API,它允许我们访问顶级项目及其属性。API 浏览器支持仍处于萌芽状态,在撰写本文时只有 Opera 12 预览版,尽管 Firefox 和 WebKit 正在努力。幸运的是,这没问题,因为这些数据对搜索引擎机器人和第三方工具仍然有用,并且在有原生 API 支持之前,我们可以使用微数据。

创造你自己的词汇

如果你在 schema.org 找不到合适的词汇,你可以考虑自己创造。以下是步骤。

  1. 制定你的词汇规则。这有点像建立一个数据库。为每种类型的数据指定名称,然后考虑每个名称的值应该/必须包含什么类型的数据(URL、日期时间、自由文本、有限制的文本……),以及某个内容是否需要成为另一个内容的子内容。
  2. 在你控制的域上创建一个 URL,最好把你的词汇表放在那里。
  3. 使用 itemtype= " "中的 URL 来引用您的词汇表。

也有很好的理由而不是来创造自己的词汇。它们可能很难创建,正如制作微格式词汇表的工作所证明的那样。对于真正特定于站点的数据,您可以使用 HTML5 定制的data-*属性或者以同样的方式使用微数据。但是要真正获得微数据的类似 API 的好处,您需要使用不仅仅是您的站点上的词汇表。要创建这样的词汇表,你需要涵盖的不仅仅是你自己的需求,而是同一主题领域其他人 80%的需求。

首先,查看一下microformats.org,看看在大致相同的区域是否有你可以微数据化的东西。之后,尝试 RDFa 词汇表。如果你仍然运气不好,试着和你专业领域的其他人合作学习一个词汇。如果你打算从开始写你自己的微数据词汇表,我们建议你先试着写一个微格式([j.mp/uf-process](http://j.mp/uf-process)<sup>39</sup>),因为你会得到很多好的反馈,他们也有关于如何写的好信息。然后很容易将得到的微格式词汇表转换成微数据词汇表。


38

也可以通过指定**、**、itemtype和使用 URL 作为itemprop名称来直接使用 RDFa 词汇表。参考位于[prefix.cc](http://prefix.cc)的 RDF 词汇表交换中心(“名称空间查找”)来找到它们。

关于微观数据的最终想法

我们浏览了微数据的构建块,这是一个简单的五属性组合,在任何元素上包含itemscopeitempropitemrefitemtypeitemid,并在<meta>上使用content。我们研究了如何组合这些属性来为内容添加复杂的语义注释和关系。我们还研究了如何使用一个公共词汇表来允许带注释的数据被广泛重用(包括被搜索引擎重用),这使得为您的网站创建一个元 API 变得很容易。

用语义数据扩展 HTML5 还有其他方法。尽管我们简要介绍了微格式,但我们不会触及 RDFa,这是一种重量级的方法,通过它,data.gov.ukdata.gov和铁杆数据极客可以注释他们的数据——也是蒂姆·伯纳斯·李在 ted 演讲中如此雄辩地推广的“链接数据网络”的基础。虽然比微数据更强大,但 RDFa 也更复杂,而且(至少对于您的作者来说)理解和实现起来有点困难。然而,如果你喜欢三元组或者一直想使用 SPARQL,那么 RDFa 可能就是你想要的。

以下是微数据的一些突出之处,以及它与微格式和 RDFa 的比较:

  • 微数据可以用于任何数据。不需要预定义的词汇表(微格式中有),尽管使用一个词汇表会使您的数据更加有用。
  • 微数据比微格式更加严格。您可以在不了解词汇表的情况下解析微数据
  • 微数据和微格式一样,相对容易手写。对于非计算机科学的人来说,RDFa 可能很复杂(好吧,反正对我们来说)。
  • 微数据没有 RDFa 的 XML 文字(值中的代码)或数据类型的对等物。换句话说,你不能明确地指定“这是一个日期”,尽管一个词汇表可以指定这个信息。

39

或者,总结每项技术:

  • 微格式很容易,在某种程度上受到 HTML 4 的限制,可以在 HTML5 中工作(有一些警告),并且很可能最终会过渡到使用新的 HTML5 元素和属性。
  • 微数据是新的(很少的工具),但作为一种轻量级的方式,它显示出了为所有常见用例的页面内容添加额外语义的前景。
  • RDFa 更强大,难度也相应增加,并且有根深蒂固的支持者。

虽然微数据和 RDFa 可以被看作是相互竞争的技术(政治!),我们个人认为它们是互补的。我们或许可以将微格式、微数据和 RDFa 之间的关系表示为从简单/有限到困难/强大的滑动标度。由于它们都使用不同的技术来添加注释,您甚至可以在同一个页面上一起使用它们(语义过载!).我们的观点是:对于设计师来说,微数据处于中间的最佳位置,但是每种添加额外语义的方法都有其优点和缺点。

总结

在这一章中,我们介绍了让我们的代码真正发光的工具。我们研究了旧的收藏夹是如何进化的,以跟上不断发展的网络的需求。我们还展示了几个新元素和属性,它们扩展了我们可以在语义上表示的内容类型。最后,我们研究了进一步扩展 HTML5 的方法,包括使用微数据。

对于家庭作业,尽可能多地使用本章的元素,同时思考它们的语义。如果你已经习惯了 HTML 4 的定义,实践也将帮助你巩固 HTML5 对变化元素的定义。最后,用微格式或微数据标记一些东西,然后使用工具用你添加的额外语义做一些事情。如此强大的力量!明智地使用它来准备一个丰富的语义蛋糕——为我们在本书的后半部分将要看到的所有精彩内容打下坚实的基础。

延伸阅读及相关链接
  • HTML5 元素索引— HTML5 医生([html5doctor.com/element-index](http://html5doctor.com/element-index))
  • 走向统一的 Ruby 模型由 Fantasai ( [fantasai.inkedblade.net/weblog/2011/ruby](http://fantasai.inkedblade.net/weblog/2011/ruby))提出
  • 微格式:为 Web 2.0 赋予你的标记能力,作者约翰·奥尔索普
  • 深入研究 html 5——“分布式”、“可扩展性”,以及马克·皮尔格林([diveintohtml5.net/extensibility.html](http://diveintohtml5.net/extensibility.html))的其他花哨词汇
  • 关联数据教程(RDFa 介绍)([ld2sd.deri.org/lod-ng-tutorial](http://ld2sd.deri.org/lod-ng-tutorial))
  • Philip jgenstedt([blog.foolip.org/2009/08/23/microformats-vs-rdfa-vs-microdata](http://blog.foolip.org/2009/08/23/microformats-vs-rdfa-vs-microdata))的微格式 vs RDFa vs 微数据
  • 谷歌帮助——丰富的片段;包含对微数据、微格式和 RDFa 的精彩介绍,以及每种语言的代码示例([www.google.com/support/webmasters/bin/topic.py?topic=21997](http://www.google.com/support/webmasters/bin/topic.py?topic=21997))**

五、富媒体

还记得网络只是一系列包含文本和图像的相互链接的文档的时代吗?没有吗?别担心。我们将给你们上一堂简短的历史课。在 90 年代中期,大多数网站包含大量的文本和一些图片。后来,一个注定要改变游戏规则的东西出现了:FutureSplash 插件。因为它是一个专有插件,而不是一个被认可的开放规范,关于它是否应该成为网络架构的一个基本部分的争论仍然存在。然而,FutureSplash 并不是唯一的一个;Real Player 和 QuickTime 也想加入这个专有插件的行列。

你可能知道故事是如何继续的——future Flash 被 Macromedia 收购,并将其重命名为 Flash,它在桌面上变得无处不在。它的成功基于这样一个事实,即它提供了许多开放标准所缺少的功能,比如视频和动画。插件,比如 Flash,解决了跨浏览器兼容的问题。但是故事将如何结束呢?Flash 和其他专有格式的未来会如何?HTML5 和开放网络的兴起会宣告专有格式的终结吗?在这一章中,我们将讨论我们前进的方向,并向您介绍 native videoaudio以及对canvasSVG(可缩放矢量图形)的简要了解,它们很可能包含答案。

闪光灯的情况

让我们明确一点:我们并不反对 Flash。事实上,恰恰相反。该插件丰富的创作工具允许习惯于编写 HTML 4.01 的开发人员为他们的站点带来动态、音频、视频、动画,最重要的是,开箱即用的跨浏览器兼容性。它对浏览器功能的增强远远超过我们基本的网络琐事所能做到的——也许直到现在。Flash 也已经成为普遍接受的向网站添加视频和音频的方法。当谈到拓展在线可能性的边界时,它是非常领先的。

曾经有一段时间,当你不能访问一个网站时,你不会被 Flash 中创建的可怕的介绍屏幕所震惊,但它已经发展成为一个能够创建高度复杂应用的复杂软件包。当使用 Flash 的原生创作语言 ActionScript 构建时尤其如此,action script 与 Adobe Flex 和 Adobe AIR 一起,鼓励熟练的开发人员在 Web 上展示他们的创造力并开辟新的天地。

Flash 插件的问题在于它是一种封闭的、专有的格式,这是进入的障碍。Flash 文件基本上只能通过使用一个昂贵的软件包来创建,这个软件包仍然掌握在一个供应商手中——Adobe。专有格式的替代品?开放标准。

专有格式与开放标准

在我们讨论 HTML5 打算如何改变游戏环境之前,让我们简单地了解一下专有格式和开放标准之间的区别。维基百科将专有格式描述为

通常由私人或组织为其应用的利益而控制,受专利保护或作为商业秘密,并旨在给予许可持有人排除他人(当前或未来)对技术的独家控制权。

[en.wikipedia.org/wiki/Proprietary_format](http://en.wikipedia.org/wiki/Proprietary_format)

Openformats.org 将开放标准描述为

公共机构或国际组织制定的标准,旨在建立软件互操作性的规范。

[www.openformats.org/en1](http://www.openformats.org/en1)

包括 Flash 在内的专有格式为可访问性、设备独立性和开箱即用的数据可移植性带来了挑战。此外,它们并不总是能很好地与开放标准或原生浏览器功能兼容。另一方面,开放标准促进了跨平台和设备的互操作性。开放标准提供了较低的准入门槛;你所需要的只是一个文本编辑器和一个浏览器,然后你就可以创建一个网站了。

正如您将看到的,即使 HTML5 也没有完全摆脱专有格式(尽管它们没有在规范中明确标识),但从长远来看,开放标准往往会因其设备和平台独立性而胜出。

说到紧要关头,如果 Adobe 或苹果明天、下周或明年破产,会发生什么?Flash 不会突然消失,但可以说,开发人员将不得不考虑另一种解决方案来交付他们的项目。相比之下,开放标准不能破产。网络是无所不包的,不应该——不,不应该——被几家兜售其专有格式的大公司所控制。

输入 HTML5 和好友

开放网络正在快速发展。HTML5 开始向我们展示只使用开放标准可以实现什么。正如你将在本章看到的,HTML5 为浏览器提供了视频和音频。它还为我们提供了canvas以及将 SVG 文件直接嵌入页面的能力。这些技术允许我们使用简单的脚本技术来绘制和操作动态的基于像素的(canvas)和基于矢量的(SVG)图像。

这些富媒体元素与强大的 API 相结合,只使用开放的 Web 标准,为提供可互操作的、可访问的、丰富的、引人注目的体验做出了巨大贡献。问题是,Flash 等专有插件愿意躺着被开放标准赶超吗?

【HTML5 是否预示着 Flash 的终结?

在 List Apart 的一篇精彩文章中,Dan Mall 将 HTML5 与 Flash 的辩论比作网络冷战。他接着说

技术本身没有好坏之分。它们只在特定情况下合适或不合适。它们是达到目的的手段,本身并不是解决方案。

[www.alistapart.com/articles/flashstandards/](http://www.alistapart.com/articles/flashstandards/)

Dan 的方法类似于我们自己的方法,因为我们相信开发者应该在他们的军械库中使用最合适的技术。事实上,如果你是一名 Flash 开发人员,你已经掌握了用canvas创造伟大事物所需的大部分技能;只要看看 Seb Lee-Delisle 的 3D particles ( [j.mp/3dparticles](http://j.mp/3dparticles)<sup>1</sup>)就知道从 ActionScript 转换成 JavaScript 有多容易了。这是因为这两个脚本都是基于 ECMAScript 语言的,这意味着在一个和另一个之间切换是相对容易的!

Flash 肯定会在未来几年继续推动在线可能的边界,游戏可能会处于这一推动的最前沿(尽管它的束缚正在减弱)。然而,即使是 Adobe 也害怕 HTML5,在 Gartner 代表 Adobe 进行的一份报告中称“HTML5 对 Adobe Flash 构成了威胁”。苹果决定不在 iPhone 或 iPad 上支持 Flash,这当然也于事无补。就连 Ricardo Cabello(你们中的一些人会称他为 Doob 先生)也从他的投资组合中删除了所有 Flash 项目,因为他“再也没有兴趣做 Flash 项目了”([j.mp/doobnoflash](http://j.mp/doobnoflash)<sup>2</sup>)。


1

2

简而言之,Flash 不会很快走向任何地方,但是希望这一章的内容会让你思考你实际上需要在你建立的下一个网站上使用哪种技术。

视频 HTML5 方式

没有一天我们不被告知视频(我们不只是在谈论 YouTube)是网络的未来。如果是这样的话,特别是对于普通用户来说,我们肯定需要一种简单、可靠的方式来包含视频内容,而不必投资昂贵的专有软件。HTML5 正好提供了这一点,直接在浏览器中用(最少)一行标记。

让我们来看看近年来我们是如何使用object标签向我们的网站添加视频的。我们确信你们都会认出 YouTube 嵌入代码。

<object width="640" height="385">   <param name="movie" value="http://www.youtube.com/v/24FNE60FRzw&hl=en_GB&fs=1&">   </param>   <param name="allowFullScreen" value="true"></param>   <param name="allowscriptaccess" value="always"></param>   <embed src="http://www.youtube.com/v/24FNE60FRzw&hl=en_GB&fs=1&"          type="application/x-shockwave-flash" allowscriptaccess="always"            allowfullscreen="true" width="640" height="385">   </embed> </object>

很丑,是吧?嗯,你可能已经猜到了,HTML5 不仅帮助我们变得更加语义化,还让我们向网站添加视频变得像 ABC 一样简单(好吧,几乎一样简单)。您需要的基本标记是

<video src="gordoinspace.webm"></video>

默认情况下,浏览器不显示任何播放控件;用户需要打开一个上下文菜单(右键单击或 cmd+单击)来播放使用该标记的视频,这不是很直观。当浏览器计算尺寸时,如果您没有显式设置视频的widthheight,您也会在加载页面时看到一个小故障。此外,用户也不会先睹为快地看到他们将要观看的内容。为了补救这种情况,我们将添加postercontrols属性以及维度(稍后我们将更详细地解释这些属性)。

<video src="gordoinspace.webm" width="720" height="405" poster="poster.jpg" controls> </video>

在 Chrome 中,你应该会看到类似图 5-1 的东西。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-1。**Chrome 中的基本视频元素

然而,标准的全局属性以及postercontrols并不是唯一可用的属性。

HTML5 中定义的标准全局属性有:

accesskey              dropzone class                  hidden contenteditable        id contextmenu            itemid dir                    itemprop draggable

让我们更详细地看一看每一个。

  • autoplay:告诉浏览器在视频下载后立即开始播放。
  • controls:显示浏览器自带的内置控件。基本控制往往包括播放/暂停按钮、计时器、音量控制和时间擦洗器。
  • crossorigin:允许或禁止使用 CORS(跨源资源共享)跨其他域共享视频。
  • height:识别视频的高度(如果您的高度/宽度比例不正确,您将会在视频的上方和下方看到黑色条纹;不会扭曲)。
  • loop:告诉浏览器在播放完成后循环播放视频。
  • mediagroup:通过创建媒体控制器,允许多个媒体元素链接在一起。因此,您可以同步多个视频或一个视频与音频。
  • muted:允许作者指定视频开始播放时是否静音。
  • poster:识别用作保持框的静止图像的位置。
  • preload:允许作者在页面加载后立即通知浏览器开始(或不开始)下载视频。preload已经取代了autobuffer属性。如果存在的话,autoplay属性可以覆盖preload属性。可用的状态有
  • none:告诉浏览器不要预加载文件。当用户单击播放时,文件将开始加载。
  • metadata:告诉浏览器仅预加载元数据(尺寸、第一帧、持续时间等。).当用户单击播放时,文件的其余部分将开始加载。
  • auto:告诉浏览器选择是下载整个文件,什么都不下载,还是只下载元数据。如果没有指定preload,这是默认状态。
  • src:标识视频文件的位置(注意,如果存在子source元素,这不是必需的,我们将在后面介绍)。
  • width:识别视频的宽度(如果你的高/宽比例不正确,你会看到视频上下有黑色条纹;不会扭曲)。

loopautoplaypreloadcontrols为布尔属性,表示如果代码中存在关键字,则值为true。如果你写的是 XHTML,那就把controls写成controls="controls"

注意:mediagroupcrossorigin属性最近才被添加到规范中,因此没有在任何浏览器中实现。

正如我们将看到的,一些浏览器还不支持video元素(或特定的编解码器——稍后会详细介绍)。不过,使用适度的降级,我们可以通过以下载视频的链接的形式提供后备内容来迎合这些浏览器。这是因为浏览器总是显示它们无法识别的 HTML5 元素中的内容。

<video src="gordoinspace.webm" width="720" height="405" poster="poster.jpg" controls> Download <a href="gordoinspace.webm>Gordo in Space</a> the movie. </video>

注意:我们不认为自动播放视频是一个好主意,主要是从可访问性(a11y)的角度来看。这同样适用于总是包含控件。事实上,迪士尼曾因拥有盲人用户无法关闭的视频和音频而对他们提起诉讼([j.mp/noaccessdisney](http://j.mp/noaccessdisney)<sup>3</sup>),你不会希望自己处于那种境地。

到目前为止很简单,对吧?不幸的是,事情从来没有这么简单,不是吗?让我们来谈谈房间里的大象。


3

视频格式

大象——不,是大象——藏在后面的是视频格式和编解码器。HTML5 规范的早期版本指定了 Theora 编解码器(见下一节),但苹果拒绝实现它。Theora 编解码器随后从规范中删除,因为浏览器供应商无法就通用编解码器达成一致。这意味着不再记录首选编解码器。

在我们深入探究哪些浏览器支持哪些编解码器之前,让我们偏离常规,简要描述一下视频容器和编解码器之间的区别。

视频容器和编解码器

我们与视频相关联的文件扩展名.mp4.avi.flv本身并不是编解码器,而是一种容器格式。想一想 ZIP 或 RAR 文件是如何包含几种类型的文件的;视频容器格式做同样的事情。容器格式应该被认为是“如何存储数据”,而编解码器应该被认为是“如何理解和播放数据”

这些容器倾向于包括多个轨道,通常至少一个用于视频,一个用于音频。音轨通过包含在音轨中的标记来同步。对于不同的语言,可以有多个音频轨道或字幕轨道(稍后将详细介绍)。容器还可以有关联的元数据,可能包括视频的标题或章节点。

你可能会想,“但是这和 HTML5 视频有什么关系呢?”答案是,为了实现 HTML5 视频跨浏览器,我们需要知道三种容器格式。

  • WebM :加入 HTML5 党的最新容器格式([j.mp/webmproject](http://j.mp/webmproject)<sup>4</sup>)。它是在 2010 年谷歌 I/O 大会上宣布的,此前谷歌收购了 On2 技术([j.mp/googleon2](http://j.mp/googleon2)<sup>5</sup>)。基于 Matroska 容器格式,它设计用于开源 VP8 视频编解码器和 Vorbis 音频编解码器。YouTube 支持 WebM 格式,前提是你已经选择加入它的 HTML5 实验([j.mp/youtubehtml5](http://j.mp/youtubehtml5)<sup>6</sup>),并且使用兼容的浏览器。
  • Ogg :开放的标准容器格式,没有任何专利限制,由 Xiph.Org 基金会([j.mp/oggtheora](http://j.mp/oggtheora)<sup>7</sup>)维护。Ogg 的视频编解码器叫做 Theora,音频编解码器叫做 Vorbis。
  • MPEG-4 :基于苹果公司的 QuickTime 容器格式 MOV ( [j.mp/mpeg4container](http://j.mp/mpeg4container)<sup>8</sup>)。它与文件扩展名.mp4.m4v相关联。MPEG 4 的缺点是它受专利保护,这可能意味着用户从 2016 年开始将不得不支付版税。MPEG 4 使用 H.264 视频编解码器。

4

5

6

7 [en.wikipedia.org/wiki/Ogg](http://en.wikipedia.org/wiki/Ogg)

我们已经介绍了我们感兴趣的容器格式,但是具体的编解码器呢?虽然编解码器的数量范围很广(即使是这三种容器格式),但我们只对以下三种感兴趣:

  • VP8 :不受任何已知专利限制的开放视频编解码器。它归谷歌所有,由谷歌收购的 On2 技术公司开发。它的质量类似于 H.264,预计在未来几年将得到进一步发展。
  • Theora :也是由 On2 科技原创(一群聪明的家伙,你不觉得吗?)但是现在由 Xiph.Org 基金会开发。像 VP8 一样,它是免费的,不受任何已知专利的限制。Theora 相当于 VP3,一般配合 Ogg 容器使用,但质量远低于 VP8 或 H.264
  • H.264:由 MPEG 集团开发,旨在以低于以前标准的比特率创建高质量的视频。H.264 可以分为不同的配置文件,以满足不同设备的需求,因此,例如,桌面设备可能比移动设备需要更高的配置文件。它可以与大多数容器格式(通常是 MPEG-4)一起使用,但缺点是它受到 MPEG-LA 的专利保护。

正如我们前面提到的,因为浏览器供应商不能就编解码器达成一致,所以规范中没有详细说明。您现在知道有三种浏览器可供选择,但是哪种浏览器支持哪种呢?

浏览器支持

所有五个主要的浏览器都支持 HTML5 video。表 5-1 显示了浏览器支持不同编解码器的当前状态。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


8

谷歌确实在 2011 年 1 月宣布他们将放弃对 H.264 ( [j.mp/chromeh264](http://j.mp/chromeh264)<sup>9</sup>)的支持,但在撰写本文时,这还没有发生,浏览器仍然支持所有三种编解码器。针对 HTML5 视频的现状,LongTail 制作了一份名为“html 5 视频的现状”的综合报告,这是任何想使用原生视频的人必读的(j.mp/h5longtail10)。

引用 Mark Pilgrim 在深入 HTML5 中的话,

没有一种容器和编解码器的组合可以在所有的 HTML5 浏览器中工作。这在不久的将来不太可能改变。为了让您的视频在所有这些设备和平台上都可以观看,您需要对您的视频进行多次编码。

[diveintohtml5.info/video.html#what-works](http://diveintohtml5.info/video.html#what-works)

随着宣布对 Flash Player ( [j.mp/adobevp8](http://j.mp/adobevp8)<sup>11</sup>)的 VP8 支持,有一个解决方法,您可以对不支持 VP8 编解码器但支持其他 HTML5 视频格式(Safari)的浏览器使用 Flash fallback。

实现跨浏览器兼容性的另一个选择是多次编码您的视频。有很多工具可以实现这一点,其中之一是 Miro 视频转换器([j.mp/miroconverter](http://j.mp/miroconverter)<sup>12</sup>),如图图 5-2 所示,可用于 PC 和 Mac。使用 Miro 转换视频非常简单,只需拖动文件,选择所需的输出格式,然后单击转换!


9

10

11

12

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-2。**米罗视频转换器

对于进一步的编码选项,Mark Pilgrim 提供了一个深入研究 HTML5 的很好的教程([j.mp/videopilgrim](http://j.mp/videopilgrim)<sup>13</sup>)。

添加视频源

我们现在已经对视频进行了三次编码,但是到目前为止,我们只能给我们的video元素添加一个src属性——休斯顿,我们有一个问题。我们可以使用 JavaScript 检测支持,并为每个浏览器提供适当的文件。然而,更可靠的方法是使用source元素。

source允许我们为我们的媒体元素指定多个备选视频(或使用audio时的音频,我们将在后面介绍),如下所示。它是一个不可见的元素,这意味着浏览器不会呈现任何东西来直观地表明它在文档中的存在。

<video poster="poster.jpg" controls width="720" height="405">   <source src="gordoinspace.mp4" type="video/mp4">   <source src="gordoinspace.webm" type="video/vp8">   <source src="gordoinspace.ogv" type="video/ogg">   Download <a href="gordoinspace.webm>Gordo in Space</a> the movie. </video>

请注意我们是如何添加三个source元素及其适当的type属性来满足所有浏览器的需求的(好吧,不完全是所有的,你可能早就注意到了,但我们会谈到这一点)。


13

注意:不要混淆source元素和src属性。

我们现在已经从video元素中移除了src属性,因为我们使用了子元素source。请注意,下载视频的链接仍然存在,主要是为那些可能在纯文本浏览器或其他设备上观看的用户。

如果不在 source 元素中添加type属性,浏览器会在意识到编解码器不受支持之前下载每个文件的一小部分。因此,您应该确保每个视频源都包含了type属性。

注意:当对 Ogg Theora 编码的视频使用type属性时,必须将其指定为video/ogg,而不是video/ogv(最后一个字母 g ,而不是 v )。这让我们困惑了好几次,混淆的原因是文件类型有一个。ogv分机。

浏览器将播放其理解格式的第一个视频。例如,在能够播放所有格式的 Chrome 6 的情况下,它将播放 MP4 文件。如果浏览器不理解视频的类型,它会简单地跳到下一个source元素,直到找到一个它理解的元素。

source元素的顺序同样重要:MP4 必须排在第一位,因为在老款 iPads 上,它只查看第一个source元素(现在已经解析)。WebM 被放在第二位,因为它的质量高于 Ogg,从而确保 Opera 10.6+和 Firefox 4+将播放 WebM 文件而不是 Ogg;Ogg 排在第三,支持 Opera 10.5 和 Firefox 3.5/3.6。久而久之(或者甚至现在,如果你愿意的话),我们可能不需要用 Ogg 来编码我们的视频,因为目前使用它的新版本浏览器也将支持更高质量的 WebM。对我们的视频进行三重编码并添加三个source元素涵盖了许多浏览器和平台,但是 IE6、7 和 8 呢?

注意:根据您的服务器配置,视频可能无法播放。如果在 Apache 服务器上是这种情况,您可能需要指定提供视频的方式。您可以通过在您的.htaccess文件中添加以下几行来做到这一点:

*AddType video/webm .webm* *AddType video/ogg .ogg* *AddType video/mp4 .mp4*

还要注意,您可能需要对audio做同样的事情。

*AddType audio/webm .webm* *AddType audio/ogg .oga* *AddType audio/mp3 .mp3*

进入我们的老朋友 Flash

没错,伙计们:虽然我们已经讨论了开放标准取代 Flash 等专有技术的好处,但在这种情况下,我们值得信赖的老朋友 Flash 先生帮助我们支持旧版本的 Internet Explorer。有许多可用的 Flash 视频播放器,因此您可以选择使用哪一个。这个例子使用了 JW Player 的非商业版本([j.mp/jwplayer](http://j.mp/jwplayer)<sup>14</sup>)。它在链接脚本后提供的默认代码如下:

<object id="player" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" name="player" width="720" height="429">         <param name="movie" value="player.swf" />         <param name="allowfullscreen" value="true" />         <param name="allowscriptaccess" value="always" />         <param name="flashvars" value="file=gordoinspace.mp4&image=poster.jpg" />         <embed  type="application/x-shockwave-flash"  id="player2" name="player2" src="player.swf"         width="720"  height="429"  allowscriptaccess="always" allowfullscreen="true" flashvars="file=file= gordoinspace.mp4&image= poster.jpg" /> </object>

通过将 Flash object与我们之前的例子相结合,我们最终得到了一个可访问的、跨浏览器的、本地解决方案。您会注意到在object中有一个img元素,供没有安装 Flash 插件的用户使用,正如您在这个完整的文档示例中看到的:

`

                  Gordo in Space         

Gordo in Space

                                                         `

14

上述技术基于 Camen Design 的 Kroc Camen 的解决方案。我们建议你阅读克罗克的“人人视频!”([j.mp/videoforeverybody](http://j.mp/videoforeverybody)<sup>15</sup>)文章,了解最新浏览器支持和陷阱的更新。还有一个“人人视频”生成器,可以让这个过程自动化一点([j.mp/vfegenerator](http://j.mp/vfegenerator)<sup>16</sup>)。

追踪元素

然而,这并不是我们可以在原生视频中使用的唯一元素。作为 HTML5 规范的相对后来者,track元素(及其相关 API,Text Track API)旨在允许作者为视频和音频指定外部定时轨道或数据。track只能用作videoaudio媒体元素的子元素。它的用法如下(为了简单起见,我们去掉了source元素):

<video src="gordoinspace.webm" width="720" height="405" poster="poster.jpg" controls>   <track kind="subtitles" src="gordo_subtitles.vtt" /> </video>

track可以取以下属性:

  • default:设置默认使用的track元素,除非用户的偏好表明另一个track更合适。
  • kind:描述该跟踪元素提供的信息类型。它可以取以下值(如果没有指定值,默认使用subtitles):
    • 对话的抄本或译本。文本将在视频上显示为覆盖图。
    • captions:类似于subtitles,但也可以包括音效或其他相关音频信息。适用于音频不可用的情况。文本将在视频上显示为覆盖图。
    • descriptions:提供当视频不可用时(例如,当用户正在使用屏幕阅读器时)媒体元素的文本描述。
    • chapters:定义章节标题以导航媒体元素的内容。
    • metadata:包括关于媒体元素的信息和内容,默认情况下不打算向用户显示。如果愿意,您可以使用 JavaScript 公开这些信息。
  • label:为文本轨道定义用户可读的标题。对于同一媒体元素中具有相同kind属性的每个轨道元素来说,label必须是唯一的。
  • src:文本轨道数据的 URL。
  • srclang:文本轨道数据的语言

15

16

现在让我们看一个带有多语言(英语、法语和德语)字幕的例子。

<video src="gordoinspace.webm" width="720" height="405" poster="poster.jpg" controls>     <track kind="subtitles" src="gordo_subtitles_en.vtt" srclang="en" label="English"  />     <track kind="subtitles" src="gordo_subtitles_de.vtt" srclang="de" label="Deutsch"  />     <track kind="subtitles" src="gordo_subtitles_fr.vtt" srclang="fr" label=" Français"  /> </video>

使我们的视频具有内置的、可互操作的可访问性,但因为它太新了,还没有任何浏览器支持它(但他们目前正在努力)。在此之前,最好的解决方法是使用 JavaScript polyfill 来提供支持(我们将在本章后面进一步讨论这些,包括一些带有track支持的)。

WebVTT

精明的人会注意到前面两个例子中的文件扩展名“.vtt”。这是一种 WebVTT (Web Video Text Tracks) ( [j.mp/w3cwebvtt](http://j.mp/w3cwebvtt)<sup>17</sup>)文件格式,用于标记外部文本轨道。这种格式以前被称为 WebSRT (Web 字幕资源轨道)([j.mp/videowebsrt](http://j.mp/videowebsrt)<sup>18</sup>),由于它与 50 多种其他定时文本格式竞争,因此存在一些争议([j.mp/annevkwebsrt](http://j.mp/annevkwebsrt)<sup>19</sup>)。所有主流浏览器都计划支持 WebVTT,微软宣布它也将支持 TTML(定时文本标记语言)。

WebVTT 目前仅在 WHATWG HTML 规范中指定,但是 W3C Web Media Text Tracks 社区组已经成立,以帮助其顺利进入 W3C 规范。

WebVTT 文件是一个非常简单的文本文件,包含许多“提示”这些提示区分文本应该何时出现以及应该显示什么文本。每个提示都有一个唯一的 ID,并且必须在自己的行上。一个简单的 WebVTT 文件如下所示(注意第一个WEBVTT行是文件有效所必需的):


17 [dev.w3.org/html5/webvtt](http://dev.w3.org/html5/webvtt)

18

19

`WEBVTT

1
00:00:01.000 --> 00:00:10.000
The first lot of subtitles displays from 1 to 10 seconds

2
00:00:15.000 --> 00:00:20.000
The next line displays from 15 to 20 seconds
and can run onto two lines`

您会注意到每个提示使用的时间格式是hh:mm:ss:msmsms.您还可以在文本周围内嵌计时器,使其以卡拉 ok 风格连续出现,如下所示:

`WEBVTT

1
00:00:01.000 --> 00:00:10.000
The first lot of subtitles <00:00:03.000> displays from <00:00:07.000>1 to 10 seconds`

你也可以选择你的字幕样式(嗯,样式可能有点夸张)。与你在第四章的中所学的一切相反,你可以用<b>表示粗体文本,<i>表示斜体,<u>表示下划线,<ruby><rt>表示错别字、红宝石文本。你也可以使用<c.className>来定义一个类,你可以用它来设置文本的样式。最后,使用<v>你可以定义一个与文本相关的声音。这使用了下面的格式<v Speaker Name>,并且将在字幕上显示演讲者的名字和标题。让我们看一个包含这些标签的例子。

`WEBVTT

1
00:00:01.000 --> 00:00:05.000
Gordo are you ready for takeoff?

2
00:00:05.000 --> 00:00:08.000
Laughs uncontrollably

3
00:00:08.000 --> 00:00:16.000
Good, we’re ready for launch
in 3, 2, … 1 …
We are <c.launch>go!

4
00:00:16.000 --> 00:00:20.000
Good, we’re ready for launch
in 3, 2, … 1

5
00:00:20.000 --> 00:00:30.000
Arrrghhhhhhhhhhh`

最后,使用 WebVTT,我们可以通过在时间戳后添加一些提示settings来指定标题出现的位置。表 5-2 显示了哪些设置可用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们来看一个例子。

`WEBVTT

1
00:00:01.000 --> 00:00:05.000 A:start T:0
Gordo are you ready for takeoff?

2
00:00:05.000 --> 00:00:08.000 A:end L:10% D:vertical
Laughs uncontrollably`

示例中的第一个提示将文本放在框架的最左侧,文本与行首对齐。第二个提示距离顶部 10%,垂直,文本与结尾对齐。在图 5-3 中可以更清楚地看到这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-3。**使用 WebVTT cue 设置在视频上显示字幕的示例

这是对 WebVTT 的温和介绍。随着规范和浏览器支持的发展,还有更多的东西需要研究、解释和学习,所以一定要跟上时代的步伐。

用视频做更多事情

总有一天,你会需要对你的视频做更多的事情,无论是创建品牌上的自定义控件,还是添加快进和快退按钮。其中一些动作可以使用 HTML5 DOM media elements API ( [j.mp/dommediaelements](http://j.mp/dommediaelements)<sup>20</sup>)来实现。因为复杂的 JavaScript 超出了本书的范围,所以我们将简要介绍一些可用的方法和属性,让您自由地进行更多的实验。伊恩·德夫林([j.mp/devlinbook](http://j.mp/devlinbook)<sup>21</sup>)的 HTML5 多媒体和西尔维娅·普发([j.mp/pfeifferbook](http://j.mp/pfeifferbook)<sup>22</sup>)的html 5 视频权威指南对此进行了更详细的解释。

注意:我们在这里讨论的与video相关的 DOM(文档对象模型)媒体元素 API 在很大程度上也适用于audio,我们将在后面介绍。

我们将从在视频中添加自定义播放和暂停按钮开始。在示例中,我们已经从 video 元素中移除了controls属性,但是我们建议在生产环境中,您在脚本中移除这些属性,以确保没有 JavaScript 的用户仍然可以看到本地控件。下面是简化的video代码:

<video src="gordoinspace.webm">   Download <a href="gordoinspace.webm>Gordo in Space</a> the movie. </video>

接下来,我们将为视频分配一个变量。


20 [www.w3.org/TR/html5/video.html#media-elements](http://www.w3.org/TR/html5/video.html#media-elements)

21

22

<video src="gordoinspace.webm">   Download <a href="gordoinspace.webm>Gordo in Space</a> the movie. </video> **<script>** **  var gordovid = document.getElementsByTagName('video')[0];** **</script>**

最后,我们将添加两个按钮来播放和暂停我们的视频。

`
  Download <a href="gordoinspace.webm>Gordo in Space the movie.


`

然后可以使用 CSS 样式化控件,并将其放置在视频上。如果需要,您可以将它们设计为只在悬停、聚焦或其他任何时候显示。这就是原生视频在浏览器中与其他开放标准协同工作的美妙之处。如果您想更进一步,可以使用以下 DOM 事件来创建完全可定制的控件:

  • volume:用于改变音频的音量;范围从 0.0 到 1.0
  • muted:无论音量大小如何,都使视频静音
  • currentTime:返回当前播放位置,以秒为单位

将前面的事件与loadeddataplaypausetimeupdateended的事件监听器结合起来,您就拥有了构建自己的控件集所需的一切。

你可以看到开始出现的可能性。由于video现在是 DOM 中的块级元素,我们可以使用 CSS 来设计它的样式,或者添加悬停或聚焦效果。在本章后面介绍canvas的时候,我们会看到更多令人兴奋的事情。

额外作业?

对于那些渴望做得更多的海狸来说,继续制作一套你自己定制的带字幕的视频吧。让谷歌成为你的朋友。

取出重物

如果编写和记住实现跨浏览器视频的所有代码似乎太难了,有许多工具可以帮助自动化这个过程。这些 polyfills 涵盖所有需要的检测,并为每个浏览器提供适当的文件。以下是我们的五大工具,排名不分先后。然而,还有更多可用的 VideoSWS (Video,参见 What Sucks)维护 HTML5 视频播放器的比较列表([j.mp/html5videochart](http://j.mp/html5videochart)<sup>23</sup>)。

JW 播放器

我们之前见过的 JW Player 是 LongTail Video 的一款完全可配置、可换肤的播放器,可以从[www.longtailvideo.com/players](http://www.longtailvideo.com/players)下载。它使用 jQuery 并为 Flash 提供了一个到标准 JW 播放器的后备(见图 5-4 )。对于目前 HTML5 视频的状态,LongTail 也是前面提到的 HTML5 视频报告状态([j.mp/h5longtail](http://j.mp/h5longtail)<sup>24</sup>))的制作者。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-4。**适用于 HTML5 的 JW 播放器

运动员

Playr 是一个非常简单的视频播放器(图 5-5 ),由 Julien‘Delphi ki’ville torte 创建。它不包括 Flash 回退,但包括对track元素的出色支持,因此它提供了字幕。此外,它可以通过键盘访问。代码和文档可在[www.delphiki.com/html5/playr](http://www.delphiki.com/html5/playr)获得。


23

24

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-5。**带字幕的 Playr 在行动

mediaelement . js-媒体元素. js

js 是约翰·戴尔创建的一个强大的跨浏览器脚本(图 5-6 )。有一系列插件可用于添加循环按钮、翻译(使用track)和视频背光——更多插件即将推出。可以从[mediaelementjs.com](http://mediaelementjs.com)下载。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-6。约翰·戴尔的 MediaElement.js

视频联播

VideoJS ( 图 5-7 )是一个小型的开源 JavaScript 库,可以跨浏览器运行。像其他玩家一样,对于不支持video的浏览器,它退回到 Flash。还有一种全窗口模式。在[videojs.com](http://videojs.com)有售。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-7。史蒂夫赫弗南和 Zencoder 公司的视频

SublimeVideo

Jilion 的 SublimeVideo Player ( 图 5-8 )是使用一个独立的 JavaScript 库构建的,该库为不太高级的浏览器提供了 Flash 后备。它有全窗口模式和全屏模式,播放列表支持,等等。您可以从[sublimevideo.net](http://sublimevideo.net)下载试用版。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-8。**来自吉利翁的 SublimeVideo

音频

我们已经看到了浏览器中的原生视频的可能性,现在是时候看看video的妹妹audio了。虽然video可能是稍微性感一点的兄弟姐妹,但audio有太多的用例,尤其是在线电台和服务,如 Last.fm 和 Spotify。下面是将audio添加到页面的标记:

<audio src="gordo_interview.ogg" controls></audio>

如您所见,它的工作方式与video非常相似,并且共享一些相同的属性和 API。audiovideo共有的属性有

  • src
  • controls
  • autoplay
  • preload
  • loop
  • muted
  • crossorigin
  • mediagroup

注意:在 HTML 中不需要指定audio元素的宽度和高度。

video一样,控件在不同的浏览器中有不同的样式(见图 5-9 中 Opera 的样式),但是你可以使用 JavaScript 创建你自己的控件。audio的媒体 API 与video的相同,使用相同的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-9。 Opera 的音频控制

到目前为止,我们所看到的并不复杂,但是我们需要再次讨论一下那些大象——音频编解码器。

音频编码解码器

video一样,HTML5 规范中没有指定音频编解码器,因为浏览器供应商支持不同的编解码器。实质上,音频编解码器将流解码为可以通过扬声器播放的格式。有几十种音频编解码器可用,但我们只对以下五种感兴趣:

  • Vorbis :没有任何专利限制的开放编解码器。它倾向于包装在 Ogg 容器中,但也可以包装在 WebM 或其他容器中。
  • MP3:1991 年标准化的受专利保护的编解码器。
  • AAC :高级音频编码的简称,用于苹果的 iTunes 商店。它受专利保护,与 MP3 不同,它定义了多个配置文件。
  • WAV :波形音频文件格式的简称,是在 PC 上存储音频的标准。WAV 文件通常很大,因此不适合流式音频;我们在这里提到它们是因为有可用的浏览器支持。
  • MP4 :主要用于视频,但也可用于音频。

有了这五种编解码器可供选择,我们确信您已经知道哪些浏览器支持不同的格式,但是让我们在下一节中阐明它。

浏览器支持

支持分布在不同编解码器的浏览器中,但是大多数浏览器(除了 IE8 和更低版本)支持不止一个编解码器,如表 5-3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

video一样,没有一个单一的编解码器可以跨浏览器工作,这意味着你必须对你的音频进行多次编码。幸运的是,正如我们将看到的,我们可以再次使用source元素来支持多种浏览器。

添加音频源

像使用video一样使用source元素,我们可以指定多个音频文件,并允许浏览器播放它理解的第一个文件。为了迎合那些不支持audio元素的浏览器,我们将添加一个下载音频文件的链接。

<audio controls>   <source src="gordo_interview.mp3" type="audio/mp3">   <source src="gordo_interview.aac" type="audio/aac">   <source src="gordo_interview.ogg" type="audio/ogg">   Download <a href="gordo_interview.ogg>Gordo interview</a>. </audio>

您可以使用本章前面介绍的相同技术为video提供跨浏览器兼容性的快速回退。如果您不想自己完成所有这些工作,您可以使用插件或库来帮助您。此外,一定要参考前面关于track元素和 DOM media elements API(“用视频做更多事情”)的章节,它们既适用于audio,也适用于video

使用 jPlayer

由 Happyworm 开发的 jPlayer ( 图 5-10 )是一个 jQuery 插件,它为兼容的浏览器提供 HTML5 音频和视频支持,并为不兼容的浏览器提供 Flash 支持。可以从[www.jplayer.org](http://www.jplayer.org)下载。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-10。**由 Happyworm 制作的 jPlayer 演示

视频和音频摘要

这就结束了我们对 HTML5 原生音频和视频的介绍。每分钟都有价值 24 小时的视频上传到 YouTube([j.mp/youtube24](http://j.mp/youtube24)<sup>25</sup>),可能是你开始尝试的时候了。在这一章的后半部分,我们将为我们的武器库添加一些动态图形元素,并展示一些如何将它们与videoaudio结合起来产生惊人效果的例子。

画布

如果你是 Mac 用户,你可能已经接触过canvas而不自知。它是由苹果公司创建的,是其 Dashboard widgets 和 Safari 的一部分。WebKit 浏览器继续这项工作,紧接着是 Mozilla 和 Opera。canvas然后成为 WHATWG 的 HTML5 版本的一部分。微软 Internet Explorer 直到第 8 版都只支持 VML(一种用于生成矢量图形的废弃标记语言),而 IE9 支持canvas。然而,如果你认为你现在不能使用它,就不要害怕;通过使用 ExplorerCanvas 库([j.mp/excanvaslib](http://j.mp/excanvaslib)<sup>26</sup>,我们可以让canvas在 IE7 上工作。这很好,但是它有什么用呢?


25 [youtube-global.blogspot.com/2010/03/oops-pow-surprise24-hours-of-video-all.html](http://youtube-global.blogspot.com/2010/03/oops-pow-surprise24-hours-of-video-all.html)

26 [code.google.com/p/explorercanvas/](http://code.google.com/p/explorercanvas/)

基于像素的自由

简而言之,canvas及其相关的 API 提供了编写脚本的能力,用于即时生成动态图像和交互。不像 SVG,我们很快就会看到,canvas是基于像素(光栅)的,允许快速渲染,但缩放性差。这也意味着更改需要重新绘制整个画布。canvas可用于创建游戏、图表、图形、交互式图形,以及在某些情况下,完整的应用;它是否是这项工作的正确工具完全是另一回事。你甚至可以将它与videoaudio结合起来,创建一些真正有趣的实验,我们稍后会看到。

canvas包括用于绘制和操作动态图像的 2D 和 3D 上下文。由于其浏览器实现的范围,我们将在这里集中讨论 2D 上下文;然而,Firefox 和 Opera 的实验版本包括对 3D 环境的支持。

虽然canvas元素保留在 HTML5 规范中,但是上下文 API(使用canvas的方法)已经被分解成它们自己独立的规范。

添加/实现画布

为了实现一个canvas并开始在我们的文档中绘图,我们需要做两件基本的事情。

  1. 向文档中添加一个canvas元素。
  2. 使用 JavaScript 获取上下文。

向文档中添加canvas就像添加任何其他元素一样。

`

             Canvas       `

为了定义可用的绘图区域,需要在 HTML 中为canvas显式设置宽度和高度。如果不设置尺寸,canvas默认为 300 × 150 像素。给它一个id可以让我们轻松地在脚本中定位这个元素。

canvas的工作方式与videoaudio完全相同,并允许不支持的浏览器在元素中回退内容。IE9 增加了对将回退内容暴露给辅助技术的支持,即使在支持canvas时也是如此。史蒂夫·福克纳已经在 Paciello 集团博客([j.mp/canvasie9](http://j.mp/canvasie9)<sup>27</sup>)上写了这方面的文章。这是工作组目前正在处理的一个问题。下面是一个带有一些回退内容的canvas的例子:

<canvas width="640" height="480" id="outerspace">   Sorry, your browser doesn't support canvas. </canvas>

就是这样;我们已经在标记中添加了canvas。如果你在浏览器中查看这个例子,你会看到,嗯,什么都没有——因为默认情况下canvas是透明的。我们需要使用 JavaScript 来真正展示我们的绘图技能。

注意:当使用canvas绘制或制作动画时,DOM 中不会出现任何东西,这意味着它不太容易访问——如果你愿意的话,它是一个黑盒。幸运的是,W3C 已经成立了一个工作组来解决这个问题。

2D 的背景

然而,在我们开始画画之前,我们需要一些可以借鉴的东西:那就是背景。把它想象成一个画板,或者更确切地说,画板中的一页。我们可以得到这样的上下文:

<script> var canvas = document.getElementById('outerspace'); var ctx = canvas.getContext('2d'); </script>

首先,我们为我们的canvas声明一个变量,并使用getElementById方法来选择我们的canvas ( outerspace)。然后我们声明第二个变量(ctx)并使用getContext方法来选择上下文(在本例中是 2D)。

为了便于访问,我们可以更进一步,使用不显眼的 JavaScript ( [j.mp/gracefuljs](http://j.mp/gracefuljs)<sup>28</sup>)来防止不受支持的浏览器出错。这是通过添加一个简单的if语句实现的。

<script> var canvas = document.getElementById('outerspace'); if (canvas.getContext){           var ctx = canvas.getContext('2d'); } else {         // canvas not supported do something } </script>

好了,无聊的事结束了,我们保证。现在我们开始画画。为了让你慢慢适应,我们从一个简单的矩形开始。为此,我们使用fillRect方法并声明 x 轴起始位置、y 轴起始位置、宽度和高度的属性。声明坐标时,canvas的网格(或坐标)空间从左上角开始,x 轴向右增加,y 轴向下增加。


27 [www.paciellogroup.com/blog/?p=670](http://www.paciellogroup.com/blog/?p=670)

28 [en.wikipedia.org/wiki/Unobtrusive_JavaScript](http://en.wikipedia.org/wiki/Unobtrusive_JavaScript)

<script> var canvas = document.getElementById('outerspace');   if (canvas.getContext){     var ctx = canvas.getContext('2d');   //set the size and shape (x, y, width, height)   ctx.fillRect(180, 180, 240, 120); } </script>

最后,我们添加一个onload函数,并将脚本添加到文档中。结果如图 5-11 所示。

`

Canvas     Sorry, your browser doesn't support canvas. ` ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Fvkdoc-html-css-zh%2Fraw%2Fmaster%2Fdocs%2Fbegin-h5c3-web-evo%2Fimg%2F9781430228745_Fig05-11.jpg&pos_id=img-hfbq2Rl5-1723651960869)

**图 5-11。**使用canvas绘制的简单矩形

我们可以使用fillStyle方法改变矩形的颜色。注意出现在 fillRect之前。正如雷米·夏普指出的,“如果你要画画,你需要先把画笔蘸到颜料罐里”([j.mp/sharpcanvas](http://j.mp/sharpcanvas)<sup>29</sup>)。fillStyle可以使用关键字(蓝色)、十六进制代码(#002654)或 rgba(参见第十一章)提供的值,如下例所示:

<script> window.onload = function() { var canvas = document.getElementById('outerspace'); if (canvas.getContext){   var ctx = canvas.getContext('2d');   ctx.fillStyle="rgba(0,149,197,0.8)";   ctx.fillRect(180, 180, 240, 120); }; </script>

如果我们希望矩形有一个轮廓而不是被填充,我们可以使用strokeRect方法,如下所示(结果见图 5-12 )。你也可以使用clearRect方法使一个区域透明。

<script> window.onload = function() { var canvas = document.getElementById('outerspace'); if (canvas.getContext){     var ctx = canvas.getContext('2d');   ctx.fillStyle="rgba(0,149,197,0.8)";   ctx.strokeRect(180, 180, 240, 120); }; </script> 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-12。**用canvas绘制的描边矩形

谢天谢地,我们没有被矩形束缚住;我们还可以绘制线条、路径(对于复杂的曲线)、渐变和文本。我们还可以处理图像、幻灯片和变换,所有这些都可以让我们展示我们的创造力。

下一个例子显示了一个简单的圆(见图 5-13 )。希望你记得你在学校学过的数学,因为你会需要它。


29 [html5doctor.com/an-introduction-to-the-canvas-2d-api](http://html5doctor.com/an-introduction-to-the-canvas-2d-api)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-13。**用canvas画的圆

提示:在 Canvas API 中,角度是用弧度来度量的,而不是度数。使用以下 JavaScript 表达式将角度转换为弧度:

*var radians = (Math.PI/180)*degrees*

要创建圆,我们遵循以下步骤:

  1. 启动路径(beginPath)。
  2. 画一个圆弧(ctx.arc),圆心位置 320,半径 240,半径 200。
  3. 将其从 0 到 2*PI 弧度(360 度)的角度旋转。
  4. 使用closePath方法关闭路径,并应用预定义的填充。

此代码示例显示了如何做到这一点:

<script> window.onload = function() { var canvas = document.getElementById('outerspace'); if (canvas.getContext){   var ctx = canvas.getContext('2d');   ctx.fillStyle = "rgba(0,149,197,0.8)";   ctx.beginPath();   // begin the path   ctx.arc(320,240,200,0,Math.PI*2,true);   // draw an arc - (x, y, radius, startAngle, endAngle, anticlockwise)   ctx.closePath();   // close path   ctx.fill(); }; </script>

如果你跟不上,重温前面的步骤,直到你理解它们。我们现在将我们的圆进一步,并添加一个梯度。为此,我们首先为渐变定义一个变量(mygrad),然后应用createLinearGradient方法并指定渐变的起点(x1y1)和终点(x2y2),如下所示:

var mygrad = ctx.createLinearGradient(300,100,640,480); // varmygrad = ctx.createLinearGradient(x1,y1,x2,y2);

现在我们有了一个包含渐变的对象,我们将使用addColorSto p 方法给它分配颜色。该方法有两个参数:positioncolorposition是一个介于 0(最小值)和 1(最大值)之间的值,它定义了颜色相对于其形状大小的位置。例如,将position设置为 0.25 会将颜色放置在渐变的四分之一处。color参数是基于 CSS 的字符串,可以使用关键字、十六进制值或 rgba。

mygrad.addColorStop(0, '#6c88ba'); // mygrad.addColorStop(position, color);

为确保渐变平滑且不占据整个圆,在线性渐变示例中添加三个色标,分别位于 0(最小值)、0.9 和 1(最大值)(结果见图 5-14 )。

`

// Define the gradient
var mygrad = ctx.createLinearGradient(300,100,640,480);
mygrad.addColorStop(0, ‘#6c88ba’);
mygrad.addColorStop(0.9, ‘rgba(0,0,0,0.5)’);
mygrad.addColorStop(1, ‘rgba(0,0,0,1)’);

// Draw the circle
ctx.fillStyle = mygrad;
ctx.beginPath();  
ctx.arc(320,240,200,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
};
` 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-14。**用canvas绘制的带有线性渐变的圆

请注意,我们没有使用径向渐变来达到这种效果。使用径向渐变稍微复杂一点,让我们来看一下。

从使用createRadialGradient方法开始,它的工作方式类似于createLinearGradient方法,增加了两个半径参数。

var radgrad = ctx.createRadialGradient(305,215,150,320,240,200); // var radgrad = ctx.createRadialGradient(x0, y0, radius1, x1, y1, radius2)

然后,我们用与线性示例相同的方式定义色标(这次我们使用四个色标)。

radgrad.addColorStop(0, '#6c88ba'); radgrad.addColorStop(0.8, 'rgba(61,71,89,0.7)'); radgrad.addColorStop(0.9, 'rgba(61,71,89,0.8)'); radgrad.addColorStop(1, 'rgba(255,255,255,1)');

最后,我们画一个矩形来放置径向渐变。

ctx.fillStyle = radgrad; ctx.fillRect(0,0,640,480); //rectangle that fills the whole canvas

让我们结合前面的代码来完成这个完整的例子。

`

// Create gradient and color stops
var radgrad = ctx.createRadialGradient(305,215,150,320,240,200);
radgrad.addColorStop(0, ‘#6c88ba’);
radgrad.addColorStop(0.8, ‘rgba(61,71,89,0.7)’);
radgrad.addColorStop(0.9, ‘rgba(61,71,89,0.8)’);
radgrad.addColorStop(1, ‘rgba(255,255,255,1)’);

// draw shapes
ctx.fillStyle = radgrad;
ctx.fillRect(0,0,640,480); };
`

你应该能看出图 5-14 和图 5-15 中两个例子的不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-15。**用canvas绘制的带有径向渐变的圆

回到线性渐变的例子,我们可以使用以下四个属性给圆形添加阴影。它们在定义渐变之后、绘制圆之前插入。

// Create a drop shadow ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 10; ctx.shadowBlur = 20; ctx.shadowColor = rgba(0,0,0,0.9);

一切都很简单。请注意,偏移量可以设置为负数,这意味着阴影不会总是出现在形状的右下方。结合我们之前的线性渐变,我们得到了下面的脚本:

`

// Define the gradient
var mygrad = ctx.createLinearGradient(300,100,640,480);
mygrad.addColorStop(0, ‘#6c88ba’);
mygrad.addColorStop(0.9, ‘rgba(0,0,0,0.5)’);
mygrad.addColorStop(1, ‘rgba(0,0,0,1)’);

//Create a drop shadow
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 20;
ctx.shadowColor = “black”;

// Draw the circle
ctx.fillStyle = mygrad;
ctx.beginPath();  
ctx.arc(320,240,200,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
};
`

如果你把这个脚本添加到你的 HTML 文档中,完成一个canvas元素,并在一个支持canvas的浏览器中打开它,你应该会得到如图图 5-16 所示的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-16。**用canvas绘制渐变和阴影的圆

看起来不错,是吧?我们认为是的。我们已经学习了一些基本的canvas绘制方法,但是你还可以从 API 中获得更多,比如使用createPattern合并图像,绘制线条、贝塞尔曲线和文本。您还可以使用变换、翻译和动画。如果你真的想把船推出去,你可以通过调用toDataURL方法把你的画布保存为图像。我们没有足够的空间在这里一一介绍,但是有一些专门介绍canvas的书籍。

IE 中的画布

我们很快就会看到人们用canvas制作的一些令人惊叹的演示例子,但是首先我们要解决你可能会问的问题,“IE 中的canvas怎么样?”

当我们第一次介绍canvas的时候,我们提到过你可以通过使用一个名为 ExplorerCanvas(excan vas . js)([j.mp/excanvaslib](http://j.mp/excanvaslib)<sup>30</sup>)的 JavaScript 库来支持 IE。它通过将你的脚本转换成微软专有的 VML 技术来工作,这与我们已经描述过的canvas API 没有什么不同。就像下载文件并在页面的head中添加一个链接一样简单,如下所示:

`

        Gordo's Space Adventures            `

30 [code.google.com/p/explorercanvas](http://code.google.com/p/explorercanvas)

在使用 excanvas.js 时,你应该意识到它的执行和渲染速度可能会很慢,这取决于你想要达到的复杂程度。以下是更多的问题:

  • 不支持径向渐变。
  • 图案必须在 x 轴和 y 轴上重复。
  • 不支持剪辑区域。
  • 阴影没有实现。

随着 IE9 包括canvas的支持,我们希望 excanvas.js 将成为过去。

画布的力量和潜力

我们已经讨论了canvas的潜力,所以现在我们将简要地看一些人们使用canvas和它的 API 创建的演示的例子。

比赛

首先,我们来看几个游戏例子。

割断绳子

《割断绳子》(图 5-17 )是 iPhone 游戏玩家的最爱,它已经被微软、ZeptoLab 和 Pixel Lab 移植到 HTML5 上。他们将游戏从 Objective-C 移植到 JavaScript,特别是利用canvas来制作图形。他们甚至发现在某些领域canvas提供了比他们在 iPhone 版本上使用的 OpenGL 更多的功能。在[www.cuttherope.ie](http://www.cuttherope.ie)找到它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-17。**使用canvas切割绳子。

帆布骑士

Canvas Rider ( 图 5-18 )允许用户控制骑手沿着一条路线行进而不会掉下来。游戏允许用户提交自己的关卡,这些关卡是用canvas创建的。访问[canvasrider.com](http://canvasrider.com)进行游戏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-18。**画布骑士,用canvas创作的游戏

3D 俄罗斯方块

另一个使用canvas、3D 俄罗斯方块(图 5-19 )以 3D 方式重现的游戏经典是由本·乔菲创作的。一定要去本的网站([www.benjoffe.com](http://www.benjoffe.com))上看看更多的canvas游戏的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-19。**用canvas制作的伪 3D 俄罗斯方块

应用

现在我们来看一些应用示例。

暗房

暗室([mugtug.com/darkroom](http://mugtug.com/darkroom))由 MugTug 创建,是一个使用canvas构建的一体化图像处理包(见图 5-20 )。暗室有一个广泛的功能集,允许设计师在飞行中裁剪,镜像和旋转图像。与 Photoshop 一样,用户可以改变图像的层次,提高亮度或对比度,或者应用默认滤镜之一,如“黑白”编辑完图像后,您可以将其保存到桌面上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-20。**mug tug 的暗室

画板

MugTug 还发布了另一款在线工具 sketchbad([mugtug.com/sketchpad](http://mugtug.com/sketchpad))。这是一个运行在浏览器中的全功能绘图包,由canvas构建(见图 5-21 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-21。**mug tug 的画板

Picozu 编辑器

Picozu Editor ( 图 5-22 )是一个用 JavaScript、HTML5 和 CSS3 构建的绘图和照片润色应用。该应用使用canvas来应用图像过滤器和拖放 API,以允许用户从他们的桌面添加图像。可以在[www.picozu.com/editor](http://www.picozu.com/editor)玩一玩。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-22。**pico zu 编辑器中的一些可用选项

将视频和音频与画布相结合

我们在本章前面谈到了新的原生媒体元素(audiovideo)是如何被设计成与canvas一起工作来创建丰富的、引人注目的在线体验的。这里有一些实际的例子,给你一些如何真正给你的网站添加一些点缀的想法。

9 元素 HTML 画布实验

9elements 的人开始尝试新的 HTML5 特性,特别是audiocanvas。他们将此与 Twitter API(搜索术语“HTML5”)和 Processing.js ( [processingjs.org](http://processingjs.org))结合起来进行粒子渲染,以创建一个漂亮的推特和粒子动画可视化,并同步到音频轨道(见图 5-23 )。这个实验的详细报道可以在 9 元素博客([j.mp/9elementsblog](http://j.mp/9elementsblog)<sup>31</sup>)上找到。


31 [9elements.com/io/?p=153](http://9elements.com/io/?p=153)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-23。**9 元素canvas实验

环境光

如果你看过飞利浦流光溢彩电视([j.mp/ambilighttv](http://j.mp/ambilighttv)<sup>32</sup>)并且印象深刻,那么这个演示就是为你准备的。流光溢彩由 Sergey Chikuyonok 创建,其工作原理是从视频的每一帧收集像素颜色数据,并将环境光反射到视频两侧的两个画布元素上。如图图 5-24 所示的效果,简直是出神入化:[j.mp/ambilightcanvas](http://j.mp/ambilightcanvas)<sup>33</sup>


32

33

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-24。Sergey Chikuyonok 的《??》流光溢彩

视频销毁

Crafty Mind 的 Sean Christmann 创建了一个结合了videocanvas元素的演示。演示的基本前提是展示画布如何与其他元素(video)结合使用,以创建令人惊叹的效果。点击视频使其“爆炸”,如图图 5-25 所示;随附的文章([j.mp/blowupvideoarticle](http://j.mp/blowupvideoarticle)<sup>34</sup>)解释了它是如何实现的。

它还提供了一些使用 CSS 对这些元素进行转换和翻译的预览。请放心,你将在第十二章中了解所有相关内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-25。**视频破坏


34

进一步画布资源

我们短暂参观了一下canvas所能提供的力量。要更详细地介绍它,需要自己写一本书,所以现在我们将向您介绍一些进一步的canvas资源,让您自己去试验:

  • 开发。歌剧:米哈伊·苏灿([dev.opera.com/articles/view/html-5-canvas-the-basics](http://dev.opera.com/articles/view/html-5-canvas-the-basics))的《HTML5 画布——基础》
  • Mozilla 开发者中心:画布教程([developer.mozilla.org/En/Canvas_tutorial](https://developer.mozilla.org/En/Canvas_tutorial))
  • HTML5 博士:雷米·夏普([html5doctor.com/an-introduction-to-the-canvas-2d-api](http://html5doctor.com/an-introduction-to-the-canvas-2d-api))的《画布 2D API 简介》
  • html 5 Doctor:Tab Atkins Jr .([html5doctor.com/video-canvas-magic](http://html5doctor.com/video-canvas-magic))的《视频+画布=魔术》
  • 画布演示:使用 HTML 5 <画布>元素([www.canvasdemos.com](http://www.canvasdemos.com))的应用、游戏、工具和教程
  • 。net 杂志:Rob Hawkes([www.netmagazine.com/tutorials/learning-basics-html5-canvas](http://www.netmagazine.com/tutorials/learning-basics-html5-canvas))的“学习 HTML5 画布的基础知识”

SVG

可缩放矢量图形是一种基于 XML 文件格式在浏览器中创建矢量图形的技术。它是 W3C 自 1999 年([www.w3.org/TR/SVG](http://www.w3.org/TR/SVG))以来积极开发的一个开放标准。我们必须指出 SVG 不是 HTML5 的部分。跟着我们重复——“SVG不是 HTML5 的部分。”然而,HTML5 确实允许内嵌 SVG,这就是我们在这里关注它的原因。

矢量功率

正如您从名称中所看到的,SVG 文件是基于矢量的,这意味着它们可以在不损失质量的情况下放大或缩小。这与canvas形成了鲜明的对比,后者是基于像素(光栅)的,不能很好地缩放。所有主流浏览器都支持基本 SVG(IE8 及以下版本除外)。HTML5 中嵌入的 SVG,也称为“内联 SVG”(我们将重点介绍),受 Chrome 7+、Internet Explorer 9+、Firefox 4+、Opera 11.5+和 Safari 5.1+支持。它可以实现很多和canvas一样的效果。一个主要的区别是每个 SVG 元素都成为 DOM 的一部分(记得我们说过canvas总是空的),允许每个对象被索引,并提供一个更易访问的解决方案。我们现在面临一个两难的选择,canvas还是 SVG?

在画布和 SVG 之间选择

我们已经提到了这样一个事实,即canvas和 SVG 都是可脚本化的图像,都可以创建形状、线条、弧线、曲线、渐变等等,但是如何在两者之间做出选择呢?

SVG 内容可以是静态的、动画的或交互式的。您可以用 CSS 对其进行样式化,或者用 SVG DOM 添加行为。因为每个元素都成为 DOM 的一部分,这意味着 SVG 相对容易访问。它还独立于分辨率,可以缩放到任何屏幕尺寸。但是,对于更复杂的形状,它的渲染速度会很慢。

相比之下,canvas使用 JavaScript API,允许我们以编程方式进行绘制。它有两个上下文对象,2D 或 3D。没有具体的文件格式,只能用脚本来画。因为没有 DOM 节点(不像 SVG ),所以您可以专注于绘图(脚本),而不会因为图像复杂性的增加而影响性能。您也可以将生成的图像保存为 PNG 或 JPG。

在决定哪种技术最适合您的项目之前,请考虑一些用例:SVG 适用于数据图表和独立于分辨率的图形、交互式动画用户界面或矢量图像编辑。适用于游戏、位图图像处理(就像我们之前看到的暗室例子)、生成光栅图形(数据可视化、分形等)。),以及图像分析(直方图等。).

总而言之,适当地使用两者。在某些情况下,这两者甚至会相互补充(例如,如果您正在创建一个可以渲染光栅和矢量图像的图像编辑器)。

如果您仍然不清楚使用哪一种,请阅读这些关于这两种技术优缺点的优秀文章:

  • 戴夫。歌剧:([j.mp/canvasorsvg1](http://j.mp/canvasorsvg1)<sup>35</sup>)
  • 站点点([j.mp/canvasorsvg2](http://j.mp/canvasorsvg2)<sup>36</sup>
  • IE 博客([j.mp/iecanvassvg](http://j.mp/iecanvassvg)<sup>37</sup>)
SVG 释放的向量

要制作 SVG 图形,您可以选择两种方法之一:使用 Adobe Illustrator 或 Inkscape(一种开源的 SVG 图形编辑器)等图形软件包,或者自己编写。猜猜我们要给你看哪个。

实现基本 SVG

编写内联 SVG 的语法相对简单;首先在 HTML 的主体中添加一个svg元素。然后将 SVG XML 名称空间和维度一起添加到元素中。但是请记住,因为它是 XML,所以您必须确保始终引用您的属性并包括那些尾随斜线。首先,我们在页面中创建了svg元素。


35dev . opera . com/articles/view/SVG-or-canvas-chopping-within-the-two

36

37 [blogs.msdn.com/b/ie/archive/2011/04/22/thoughts-on-when-to-use-canvas-and-svg.aspx](http://blogs.msdn.com/b/ie/archive/2011/04/22/thoughts-on-when-to-use-canvas-and-svg.aspx)

`<!doctype html>

      SVG   <!—SVG content will go here --> `

接下来,我们将基本的 SVG 形状元素添加到父 SVG 元素中。有几种基本形状可供选择:rectcircleellipselinepolylinepolygon。我们将从创建一个简单的矩形开始。这些例子可以在前面提到的所有浏览器中运行。

`<!doctype html>

      SVG    `

你应该会看到类似于图 5-26 的东西。属性是不言自明的。xy值代表绘制的起始坐标(从 SVG 元素的左上角开始)。这意味着矩形将从 SVG 元素的左边缘开始绘制 150 像素,从顶部开始绘制 150 像素。strokefill值可以指定为十六进制代码、关键字、rgba 或 rgba 值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-26。**用 SVG 创建的矩形

我们现在将创建与我们对canvas所做的相同的例子,以允许您比较两者。首先,使用基本的circle形状创建一个圆。

<circle fill="#6c88ba" stroke="red" cx="150" cy="150" r="150"/>

cxcy值代表圆心,r代表半径。将我们之前例子中的矩形替换为圆形,效果应该如图 5-27 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**图 5-27。**用 SVG 创建的圆

我们现在继续添加一个渐变。这是通过创建一组定义(defs)并指定诸如渐变类型(linearGradient)、id ( id="MyGradient")、角度(gradientTransform="rotate(45)")和一系列色标(<stop ... />))等参数来实现的。

<defs>   <linearGradient id="MyGradient" gradientTransform="rotate(45)">     <stop offset="0%" stop-color="#6c88ba" />     <stop offset="90%" stop-color="#677794" />     <stop offset="100%" stop-color="#6e747f" />   </linearGradient> </defs>

现在我们已经定义了渐变,我们需要将它应用到圆形。这是通过引用带有url分隔符的圆上fill属性的渐变id值(MyGradient)来实现的。这与我们之前使用canvas达到的效果相同(见图 5-28 )。

`

      SVG                              ` `       


` ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgitee.com%2FOpenDocCN%2Fvkdoc-html-css-zh%2Fraw%2Fmaster%2Fdocs%2Fbegin-h5c3-web-evo%2Fimg%2F9781430228745_Fig05-28.jpg&pos_id=img-VArKJnjK-1723651960872)

**图 5-28。**用 SVG 创建的带渐变的圆

你也可以用 SVG 创建径向渐变,还有更多。当嵌入 HTML5 时,我们仅仅触及了这种强大语言的表面。我们希望我们已经吊起了您的胃口,并说服您进一步研究 SVG 可以实现什么。

SVG 相关阅读

如果您有兴趣了解更多关于 SVG 的知识,我们强烈推荐以下资源:

  • Dev。作品 : SVG 文章([dev.opera.com/articles/svg](http://dev.opera.com/articles/svg)
  • Mozilla 开发者中心:“HTML 中的 SVG 简介”([developer.mozilla.org/en/svg_in_html_introduction](https://developer.mozilla.org/en/svg_in_html_introduction))
  • Carto:net :关于 SVG 的例子和论文([www.carto.net/papers/svg](http://www.carto.net/papers/svg))
  • 拉斐尔:IE 中支持 SVG 的库([raphaeljs.com](http://raphaeljs.com))
  • 一份清单:Brian Suda([www.alistapart.com/articles/svg-with-a-little-help-from-raphael](http://www.alistapart.com/articles/svg-with-a-little-help-from-raphael))的《拉斐尔的小小帮助下的 SVG》

总结

正如你在本章看到的,在浏览器中使用富媒体的可能性是无限的。通过组合我们描述的一种或多种技术,可以创建令人惊叹的效果,迄今为止,只有使用 Flash 或其他专有插件才能实现这种效果。在我们的浏览器中拥有这种原生多媒体内容的好处意味着不再需要插件;浏览器提供了内置键盘辅助功能的本机控件。最后,由于不需要插件,站点性能将得到提高。

通过介绍如何在 HTML5 文档中实现videoaudiocanvas和 SVG,我们希望我们已经让您看到了在线使用富媒体的新机遇。现在由你来打破常规,创造真正引人注目的、开放的、可访问的交互体验。

至于 Flash 和其他插件,还没有定论它们是否已经死亡,但有一点是肯定的——竞争对手正在迎头赶上。

作业

我们把你的作业分成两部分。首先将图书网站上提供的文件编码成足够的格式,以确保跨浏览器的兼容性,然后使用videoaudio元素将它们显示在您的示例站点上。如果你很感兴趣,你可以完成我们之前提到的额外作业,创建你自己的自定义游戏控件。

其次,选择canvas或 SVG 来生成一个简单的图表,显示地球、月亮和太阳在轨道上运行,并将其添加到您的站点。在根据所提供的链接进行进一步研究之后,继续制作图表动画。