HTML5 视频操作手册(二)

部署运行你感兴趣的模型镜像

原文:zh.annas-archive.org/md5/E8CC40620B67F5E68B6D72199B86F6A9

译者:飞龙

协议:CC BY-NC-SA 4.0

第五章:学会喜欢表单

在本章中,我们将涵盖:

  • 显示占位符文本

  • 为表单字段添加自动对焦

  • 使用 HTML5 和 CSS3 对表单进行样式设置

  • 使用电子邮件输入类型

  • 使用 URL 输入类型添加 URL

  • 使用数字标签

  • 使用范围标签

  • 创建搜索字段

  • 创建一个选择器来显示日期和时间

介绍

“我们已经遇到了敌人,他就是我们自己。” - Pogo

无聊。乏味。无聊。为什么当网页用户在网上看到交互式表单时,他们的眼睛会发直,头脑会麻木?这位作者认为,问题至少部分在于安排表单字段的信息架构师,而在较小程度上在于编码的前端开发人员。

诚然,表单并不性感。但是如果你是一个网页开发人员(如果你正在阅读这篇文章,很可能是这样),那么你的职业生涯中可能会有某个时候被要求标记和设计某种形式的表单。如果你害怕编写那个表单,想象一下你在用户身上制造的恐惧。现在结束了。

你已经成熟,并寻求值得这种成熟的新挑战。如果我们能停止担心并学会喜欢表单,那么我们的受众实际上也更有可能喜欢它们。

在本章中,我们将看一些 HTML5 用于交互式表单的实际例子,包括显示占位符文本,为表单字段添加自动对焦,使用 HTML5 和 CSS3 对表单进行样式设置,使用电子邮件输入类型,使用 URL 输入类型添加 URL,使用数字标签,使用范围标签,创建搜索字段,以及创建一个选择器来显示日期和时间。

现在让我们开始吧!

显示占位符文本

我们想要检查的第一个新的 HTML5 表单功能是本地显示占位符文本的能力。

如何做…

我们都曾使用过 - 甚至创建过 - 表单占位符文本。但现在有了 HTML5,我们将以稍有不同且更有效的方式来做。Packt Publishing 网站具有搜索整个网站或仅搜索书籍/电子书的功能。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_01.jpg

一旦用户点击这两个表单字段中的一个,占位符文本就会消失。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_02.jpg

这是通过使用值属性来显示占位符文本的传统方法:

<form action='/search'>
<div id="search-site">
<input type="text" class="form-text" name='keys' value="Search entire site" onclick='clearIf(this, "Search entire site")'/>
</div>
<div id="search-button-site">
<input type="image" src="img/search- button.png">
</div>
</form>
<form action='/books'>
<div id="search-books">
<input type="text" class="form-text" name='keys' value="Search only books/eBooks" onclick='clearIf(this, "Search only books/eBooks")'/>
</div>
<div id="search-button-books">
<input type="image" src="img/search- button.png">
</div>
</form>

使用placeholder属性而不是value会导致:

<form action='/search'>
<div id="search-site">
<input type="text" class="form-text" name='keys' placeholder="Search entire site" onclick='clearIf(this, "Search entire site")'/>
</div>
<div id="search-button-site">
<input type="image" src="img/search- button.png">
</div>
</form>
<form action='/books'>
<div id="search-books">
<input type="text" class="form-text" name='keys' placeholder="Search only books/eBooks" onclick='clearIf(this, "Search only books/eBooks")'/>
</div>
<div id="search-button-books">
<input type="image" src="img/search- button.png">
</div>
</form>

它是如何工作的…

placeholder属性可以取代value属性来在表单中显示占位符文本。在这种情况下,开发人员添加了一个onclick事件处理程序来适应旧版浏览器。这是另一个例子,优秀的语义增加了标签的额外含义。

还有更多…

记住 - 并计划 - 当用户点击每个表单字段时,占位符文本本身将消失。如果用户在不填写表单字段的情况下点击其他地方,placeholder将重新出现。

仅文本

placeholder属性只能包含文本。我们不能在其中包含其他标记、图像或任何其他元素。

拥抱斜体

默认情况下,占位符文本将以斜体显示。不幸的是,没有很好的方法来改变这一点。与其对头撞墙,不如事先知道这一点,并说服你的设计师,文本应该是斜体,并让他专注于真正重要的事情。

浏览器支持

支持新的placeholder属性的 Web 浏览器。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_03.jpg

另请参阅

Build Guild 是全国网页人员的每月聚会。使用 HTML5(并使用占位符属性!)在buildguild.org构建,开发人员可以每隔几周聚在一起喝酒聊天。已经在城市建立了本地分会,例如:德克萨斯州阿比林;纽约州奥尔巴尼;蒙大拿州比灵斯;密歇根州大急流城;康涅狄格州哈特福德;肯塔基州路易斯维尔;威斯康星州密尔沃基;纽约市,纽约州;宾夕法尼亚州费城;宾夕法尼亚州匹兹堡;密苏里州圣路易斯;马萨诸塞州塞勒姆。

如果你所在地区还没有 Build Guild,请创建一个!联系网站所有者buildguild.org开始!胡子是可选的。

为表单字段添加自动对焦

过去,我们不得不依赖 JavaScript 来为特定的表单字段添加输入焦点,但现在不再需要了!现在我们可以在 HTML5 中本地实现这个功能!

如何做…

Ally Creative 在他们的联系表单中有效地使用了autofocus功能,网址是allycreative.net/contact

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_04.jpg

它是如何工作的…

他们是这样做的:

<form action="" method="post">
<ol id="left">
<li>
<label for="contact-name" class="label-fade">Jane Doe of ACME Corporation</label>
<input type="text" id="contact-name" name="contact-name" title="Name / Business" autofocus /></li>
<li>
<label for="contact-mail" class="label- fade">jane.doe@acme.com</label>
<input type="text" id="contact-mail" name="contact-mail" title="E-mail Addy" /></li>
<li>
<label for="contact-phone" class="label-fade">541 / 567- 5309</label>
<input type="text" id="contact-phone" name="contact-phone" title="Phone Number" /></li>
<li>
<label for="contact-budget" class="label-fade">Project Budget</label>
<input type="text" id="contact-budget" name="contact-budget" title="Budget" /></li>
<li><input type="hidden" id="contact-human" name="contact-human" title="Human" /></li>
</ol>
<ol id="right">
<li>
<label for="contact-subject" class="label-fade">Subject</label>
<input type="text" id="contact-subject" name="contact-subject" title="Budget" /></li>
<li>
<label for="contact-body" id="textarea-label" class="label- fade">Say something.</label>
<textarea id="contact-body" name="contact-body" title="Contact Copy"></textarea></li>
<li class="f-right"><span id="required"></span> <input type="image" src="img/button.png" id="submit-button" alt="Submit!" /></li>
</ol>
</form>

Ally Creative 的开发人员只需将autofocus属性应用于联系人姓名的表单字段,并添加适当的样式来改变背景颜色,就创建了一个流畅、互动的表单,用户很容易完成。

还有更多…

新的 HTML5 autofocus属性旨在适用于所有表单控件。所以无论你是收集用户的姓名、地址、电话号码还是其他数据,都要聪明地使用autofocus的能力!

每页一个

请记住,每个页面只能设置一个表单字段为autofocus

旧浏览器

一会儿,你会看到目前只有两个现代浏览器支持autofocus。幸运的是,旧浏览器会简单地忽略这个属性。考虑到像autofocus这样的工具可以丰富那些能看到它的用户的体验,而不会损害或降低那些使用较差浏览器的用户体验。无害,无犯。

浏览器支持

支持新的autofocus属性的 Web 浏览器:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_05.jpg

另请参阅

Mozilla 的“HTML5 的人”视频系列介绍了 HTML5 运动的许多领军人物。Remy Sharpe,我们在其他地方使用过的“HTML5 Shim”的作者,是一位 JavaScript 工匠。当他描述新 HTML5 规范的最喜欢的方面时,这应该不足为奇:

“对我来说,HTML5 最令人兴奋的方面是 JavaScript API 的深度。向 Joe Bloggs 解释,实际上这个新规范的 HTML 并不是大部分 HTML;它主要是 JavaScript,这是相当棘手的。”

阅读并观看完整的采访:hacks.mozilla.org/2011/01/people-of-html5-remy-sharp

使用 HTML5 和 CSS3 为表单设置样式

作者见过的使用 HTML5 和 CSS3 创建表单的最简单但最美丽的例子之一是加拿大 FoundationSix 的,网址是foundationsix.com/contact。他们是这样做的。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_06.jpg

如何做…

FoundationSix 团队从一个相当简单的联系表单标记开始。请注意,出于篇幅考虑,这个例子中省略了冗长的国家下拉列表。

它是如何工作的…

<form id="contactf6" method="post" action="http://foundationsix.com/index.php" enctype="multipart/form-data" >
<fieldset id="contactinfo">
<ul>
<li>
<label for="name">Name</label>
<input id="name" name="name" type="text" class="required">
</li>
<li>
<label for="email">Email</label>
<input id="email" name="email" type="text" class="required email">
</li>
<li>
<label for="website">Website</label>
<input id="website" name="website" type="text" class="required">
</li>
<li>
<label for="country">Country</label>
<select id="country" name="country" class="selectors">
<option selected value="">Please Select...</option>
</select>
</li>
</ul>
</fieldset>
<fieldset id="natureinfo">
<ul>
<li class="selectli">
<label for="nature">Nature</label>
<select id="nature" name="nature" class="selectors">
<option selected value="Get A Quote">Get A Quote</option>
<option value="Get More Info">Get More Info</option>
<option value="Say Hello">Say Hello</option>
</select>
</li>
<li class="selectli showmore">
<label for="scope">Scope</label>
<select id="scope" name="scope" class="selectors">
<option selected value="">Please Select...</option>
<option value="Complete Website Design">Complete Website Design</option>
<option value="Design Only">Design Only</option>
<option value="Coding Only">HTML / CSS Coding Only</option>
<option value="Other">Other</option>
</select>
</li>
<li class="selectli showmore">
<label for="budget">Budget</label>
<select id="budget" name="budget" class="selectors">
<option selected value="">Please Select...</option>
<option value="$2,500-$5,000">$2,500-$5,000</option>
<option value="$5,000-$7,500">$5,000-$7,500</option>
<option value="$7,500-$10,000">$7,500-$10,000</option>
<option value="$10,000-$15,000">$10,000-$15,000</option>
<option value="$15,000-$20,000">$15,000-$20,000</option>
<option value="$20,000-$50,000">$20,000-$50,000</option>
<option value="$50,000+">$50,000+</option>
</select>
</li>
<li class="selectli showmore">
<label for="timeframe">Timeframe</label>
<select id="timeframe" name="timeframe" class="selectors">
<option selected value="">Please Select...</option>
<option value="Right Away">Right Away</option>
<option value="Within 1 Month">Within 1 Month</option>
<option value="Within 2 Months">Within 2 Months</option>
<option value="Within 3 Months">Within 3 Months</option>
<option value="Within 6 Months">Within 6 Months</option>
<option value="Don't Know Yet">Don't Know Yet</option>
</select>
</li>
</ul>
</fieldset>
<fieldset id="message">
<ul>
<li>
<label for="messagetext">Message</label>
<textarea id="messagetext" name="message"></textarea>
</li>
</ul>
</fieldset>
<div id="submitbutton"><input type="submit" name="submit"></div>
</form>

团队为这个联系页面提供了一个特殊的样式表。请注意它是多么干净,只定义了必要的值,而省略了任何多余的东西。

html {
background: url(../img/sitebg.jpg) repeat; -webkit-font-smoothing: antialiased;
}
body {
color: #8a8a8a; font: 13px/19px "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; background: url(../img/subbg.jpg) repeat-x;
}
#contactform {
float: left; width: 498px; margin-bottom: 40px;
}
#formtop {
height: 97px; width: 498px; background: url(../img/formtop.png) no-repeat;
}
#formtop h1 {
text-indent: -9999px; width: 445px; height: 57px; margin: 0 auto; background: url(../img/formheader.png) no-repeat; position: relative; top: 39px;
}
#formcontent {
background-image: url(../img/formrepeat.png); width: 498px; background-position: 1px;
}
form {
width: 445px; margin: 0 auto;
}
form label {
font: 13px "ClarendonRoman", Georgia, Times, serif; color: #525250; letter-spacing: 2px; text-transform: uppercase; float: left; position: relative; top: 4px;
}
form label.error {
text-transform: none; letter-spacing: 0; color: #a21714; font: 15px "SeanRegular", Courier New, Courier New, Courier6, monospace; margin-top: -10px; clear: both; padding: 0px 0px 10px 21px; background: url(../img/errow.png) no-repeat 0 0;
}
form ul {
padding-top: 10px;
}
form ul li {
padding-top: 10px; clear: both; overflow: hidden;
}
form ul li.selectli {
padding-bottom: 10px;
}
form select, form input {
float: right;
}
form input {
border-bottom: 1px dashed #989895; border-right: none; border-left: none; border-top: none; color: #4f4f4f; background: none; outline: none; position: relative; bottom: 13px; font: 16px "SeanRegular", Courier New, Courier New, Courier6, monospace; letter-spacing: 1px;
}
form input:focus {
border-bottom: 1px dashed #000; -webkit-transition:border 0.3s ease-in; -moz-transition:border 0.3s ease-in; -o-transition:border 0.3s ease-in; transition:border 0.3s ease-in;
}
form select {
width: 300px;
}
input#name {
width: 370px;
}
input#email {
width: 360px;
}
input#website {
width: 340px;
}
fieldset#contactinfo {
padding-bottom: 23px; border-bottom: 1px solid #a7a7a4;
}
fieldset#natureinfo {
margin-top: 4px;
}
fieldset#message {
background: url(../img/messagebar.png) top no-repeat; width: 445; margin-top: 25px;
background: url(../img/messagebar.png) top no-repeat; width: 445; margin-top: 25px;
}
fieldset#message label {
display: none;
}
textarea#messagetext {
margin-top: 4px; width: 445px; height: 150px; border: none; background: none; outline: none; resize: none; overflow: auto; color: #4f4f4f; font: 16px "SeanRegular", Courier New, Courier New, Courier6, monospace; letter-spacing: 1px; float: left; display: block;
}
#submitbutton {
float: right;
}
#submitbutton input {
cursor: pointer; background: url(../img/submit.png) no-repeat; width: 445px; height: 86px; border: none; text-indent: -9999px; position: relative; bottom: 10px;
}
#submitbutton input:hover {
background-position: 0 -86px;
}
span#formbottom {
background: url(../img/formbottom.png) no-repeat; width: 498px; height: 108px; display: block;
}
#othercontact {
float: right; width: 566px; margin-bottom: 40px;
}
#map {
width: 552px; height: 269px; background: url(../img/map.jpg) center no-repeat rgb(233,233,228); background: url(../img/map.jpg) center no-repeat rgba(255,255,255,0.3); padding: 6px; border: 1px solid rgb(249,249,248); border: 1px solid rgba(255,255,255,0.7); margin-bottom: 28px; position: relative;
}
span#mappointer {
width: 77px; height: 80px; display: block; position: absolute; top: 66px; left: 257px; background-image: url(../img/map-pin.png);
}
section.subcontact {
float: left; width: 267px; position: relative; padding-left: 3px; border-top: 6px solid #d3d2c5; -webkit-transition:border 0.4s ease-in; -moz-transition:border 0.4s ease-in; -o-transition:border 0.4s ease-in; transition:border 0.4s ease-in;
float: left; width: 267px; position: relative; padding-left: 3px; border-top: 6px solid #d3d2c5; -webkit-transition:border 0.4s ease-in; -moz-transition:border 0.4s ease-in; -o-transition:border 0.4s ease-in; transition:border 0.4s ease-in;
}
section.subcontact:hover {
border-top: 6px solid #cc7b58; -webkit-transition:border 0.3s ease-in; -moz-transition:border 0.3s ease-in; -o-transition:border 0.3s ease-in; transition:border 0.3s ease-in;
}
section.subcontact h2 {
padding-top: 17px; color: #5a5a5a; font: 20px "ClarendonRoman", Georgia, Times, serif; margin-bottom: 10px; letter-spacing: -0.05em;
}
section.subcontact p {
margin-bottom: 16px; width: 260px;
}
section.subcontact.subright {
position: relative; left: 25px;
}
ul.iconlist {
padding-top: 6px;
}
ul.iconlist li {
padding: 12px 25px; border-top: 1px dashed #b2b2ab;
}
li#mapicon {
background: url(../img/icons/map.png) no-repeat 0 14px;
}
li#emailicon {
background: url(../img/icons/mail.png) no-repeat 0 13px;
}
li#vcardicon {
background: url(../img/icons/card.png) no-repeat 0 13px;
}
li#twittericon {
background: url(../img/icons/twitter.png) no-repeat 0 13px;
}
li#docicon {
background: url(../img/icons/doc.png) no-repeat 3px 13px;
}

还有更多…

大部分情况下,为 HTML5 添加层叠样式表就像为 XHTML 或以前版本的 HTML 添加 CSS 一样。只是现在我们有额外的标签需要跟踪。

提示

请记住,HTML5 和 CSS3 是两回事。人们经常把它们混在一起——就像他们对“Web 2.0”这个术语做的那样,直到这个术语最终失去了所有意义(如果它确实有任何意义的话)。我们会滥用“HTML5”这个术语,以至于最终失去所有意义吗?或者它已经发生了?只有你才能防止森林火灾。

旧浏览器

在为 HTML5 设置样式时,我们需要注意两件事:

  1. 当一些新元素还不被所有浏览器支持时,如何为其设置样式。

  2. 当新的 HTML5 元素在任何给定的浏览器中不被支持时,备用方案是什么样子的。

测试,测试,测试

在样式化 HTML5 时,关键是在浏览器中进行测试。为了我们的客户和整个网络开发的利益,我们被迫了解在浏览器中发生的事情,并根据我们的经验进行调整。

关于伪类

CSS3 提供了一些新的伪类,用于区分必填表单字段和非必填字段。我们将把这些与内置的 HTML5 表单验证结合起来:

  • :required - 让我们根据所需的内容来设置字段样式

  • :optional - 让我们根据所需的内容来设置字段样式

  • :valid - 将与表单验证一起使用

  • :invalid - 将与表单验证一起使用

  • :in-range - 适用于最小和最大字符,比如电话号码

  • :out-of-range - 适用于最小和最大字符,比如电话号码

另请参阅

如果您想尝试使用 CSS3 来样式化 HTML5,Blue Griffon 的开发人员创建了bluegriffon.org,这是一个新的所见即所得的网络内容编辑器。该工具支持多种语言,允许用户在不太考虑代码的情况下使用网络标准。

使用电子邮件输入类型

HTML5 支持的众多新输入类型之一是email。有多少次您使用<input type="text" />构建表单,意图收集电子邮件地址?现在我们可以使用更具语义的东西!稍后,我们将看到这也支持表单验证。

如何做…

以前的 FoundationSix 示例可以很容易地转换为这种新的输入类型。而不是:

<li>
<label for="email">Email</label>
<input id="email" name="email" type="text" class="required email">
</li>

我们可以简单地更改输入类型,最终得到:

<li>
<label for="email">Email</label>
<input id="email" name="email" type="email" class="required email">
</li>

在视觉上,<input type="email" />标签看起来与<input type="text" />完全相同。区别在于浏览器对信息的处理方式。

工作原理…

将类型从"text"更改为"email"允许较新的浏览器验证用户输入的是否真的是有效的电子邮件地址。请注意,服务器无法确定电子邮件帐户是否处于活动状态,只能确定地址本身是否格式良好。

还有更多…

那么,如果提交的电子邮件地址无效会发生什么?事实上,情况仍未明朗。Opera 浏览器有一个实验性的错误消息,Firefox 有自己的实验性附加组件。不幸的是,这是一个灰色地带,我们必须耐心等待浏览器以一致的方式处理它。

浏览器支持

但是关于<input type="email" />的酷炫之处在于:浏览器支持它!嗯,有点。即使不理解<input type="email" />的浏览器也会默认回到<input type="text" />,所以它仍然有效。太棒了!

无需 JavaScript

正如我们将在其他情况下看到的那样,HTML5 中的<input type="email" />允许我们停止使用 JavaScript 来实现类似的结果。我们不再需要使用行为层来弥补标记或表现层的不足。

验证的发展

表单验证已经从互联网的开始发展。在最早期,开发人员被迫使用诸如 CGI 脚本之类的技术来提交表单并完全重绘结果页面。只有在页面提交到服务器之后,用户才能知道他们的信息是否被接受。如果没有,他们就必须重新开始。

随着时间的推移,开发人员学会了使用 AJAX 来执行表单的客户端验证。这很有效,但重要的工作落在了 JavaScript 身上。当 JavaScript 被关闭或需要满足无障碍要求时,这就带来了挑战。

现在有了 HTML5,一些验证可以在浏览器中进行,而不需要将信息发送到服务器或依赖 JavaScript。虽然不如 AJAX 解决方案那样强大,但这种类型的验证可以捕获许多最常见的错误类型。

使用 URL 输入类型添加 URL

HTML5 支持的许多新输入类型之一是URL。你有多少次构建了一个使用<input type="text" />的表单,意图收集一个网站地址?现在我们可以使用更语义上正确的东西!稍后我们将看到这也支持表单验证。

如何做…

以前的 FoundationSix 示例也可以轻松转换为这种新的输入类型。而不是:

<li>
<label for="website">Website</label>
<input id="website" name="website" type="text" class="required">
</li>

我们可以简单地更改输入类型,最终得到:

<li>
<label for="website">Website</label>
<input id="website" name="website" type="URL" class="required">
</li>

<input type="email" />一样,<input type="URL" />标签在视觉上看起来与<input type="text" />相同。不同之处再次在于浏览器对输入的信息的处理方式。

工作原理…

将类型从"text"更改为"URL"允许更新的浏览器验证用户输入的是否实际上是一个有效的网站地址。请注意,服务器无法确定网站是否活动,只能确定地址本身是否格式良好。

还有更多…

那么,如果提交的网站地址无效会发生什么?事实上,这里的情况还不明朗。不幸的是,这是一个灰色地带,我们需要耐心等待,直到浏览器以一致的方式处理它。

浏览器支持

但是,关于<input type="URL" />的酷事在于:浏览器支持它!嗯,有点。即使不理解<input type="URL" />的浏览器也会默认回到<input type="text" />,所以它仍然有效。太棒了!

无需 JavaScript

正如我们将在其他情况下看到的那样,HTML5 中的<input type="URL" />允许我们停止使用 JavaScript 来实现类似的结果。我们不再需要使用行为层来弥补标记或表示层的不足。

接下来是什么?

随着浏览器的发展,将来我们可能会看到一些实现,允许浏览器对<input type="URL" />做一些更智能的事情,比如预取一个网站图标以在评论字段中显示。时间会告诉我们。

另请参阅

乐队 Arcade Fire 与电影制作人 Chris Milk 合作,为 Chrome 浏览器创建了基于乐队歌曲"We *Used To Wait"*的互动在线电影"The Wilderness Downtown",网址为thewildernessdowntown.com,完全使用 HTML5 和 CSS3。该网站因其使用画布、HTML5 视频、谷歌地图等而成为有史以来最受关注的 HTML5 体验之一。

使用数字标签

HTML5 现在允许用户在一系列数字中进行选择。例如,如果您希望您的观众购买商品,您可能希望他们使用整数。毕竟,谁会订购 2 双鞋半?

如何做…

如果我们继续以购买鞋子的例子,我们可以开发一个这样的表单:

<form>
<label>How many shoes would you like to purchase?<label>
<input type="number" name="quantity" min="2" max="6" step="2" value="2" size="4" />
</form>

请注意,在input中,我们可以选择性地指定可以订购的最小数量(2)和最大数量(6)。在这种情况下,step允许我们确保用户只能以成对的方式订购鞋子,而value设置了显示的初始数量。然后,size控制input框的宽度。

工作原理…

指定<input type="number">将显示带有上下箭头的新表单控件,允许用户增加和减少字段中的值。这些通常被称为“微调器”或“微调框”。您还可以设置此字段的增量:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_07.jpg

还有更多…

新的<input type="number" />标签在在线电子商务之外还有用途。例如,我们可以想象一个非营利组织使用它来设置一个允许用户捐赠固定金额的表单。由于组织有时会为不同的捐款金额提供奖品,表单可以被创建为只允许以这些最低增量输入。

浏览器支持

目前<input type="number" />只受 Opera 以及基于 Webkit 的浏览器(如 Chrome 和 Safari)支持。但是关于<input type="number" />有个很酷的事情:像<input type="email" /><input type="URL" />一样,其他浏览器也支持它!嗯,有点。就像这些标签一样,即使不理解<input type="number" />的浏览器也会默认回到<input type="text" />,所以它仍然有效。太棒了!

没有 JavaScript

正如我们将在其他示例中看到的那样,HTML5 中的<input type="number" />允许我们停止使用 JavaScript 来实现类似的结果。我们不再需要使用行为层来弥补标记或表现层的不足。

使用 range 标签

HTML5 现在允许我们创建一种全新的输入方式。range 标签创建了一个滑块控件,允许用户在一系列值中进行选择。这以前很困难,但现在不是了!看看吧!

如何做…

有趣的是,我们可以使用几乎与数字示例中相同的代码,只是将输入类型更改为"range"。以下是如何做到的:

<form>
<label>How many shoes would you like to purchase?<label>
<input type="range" name="quantity" min="2" max="6" step="2" value="2" />
</form>

请注意,我们可以使用相同的可选min、max、step、valuesize属性。

它是如何工作的…

指定<input type="range">将显示带有滑块的新表单控件,允许用户增加和减少字段中的值:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_08.jpg

还有更多…

<input type="range">标签还有许多其他用途,远远超出了电子商务。实际上,由于我们看不到当前选择的值,购物可能不是这个新标签的最佳用途。作者可以想象使用<input type="range">用于基于 Web 的音乐播放应用程序,用户可以在不必看到特定音量数字的情况下,直观地增加或减少音量。

使用时要小心

不幸的是,没有非 JavaScript 的方法来显示范围输入标签的当前选择值。希望随着 HTML5 的进一步定义和更多浏览器支持其原生控件,我们将能够更好地控制它。在那之前,请谨慎使用。

没有 JavaScript

正如我们将在其他示例中看到的那样,HTML5 中的<input type="range" />允许我们停止使用 JavaScript 来实现类似的结果。我们不再需要使用行为层来弥补标记或表现层的不足。

浏览器支持

<input type="number" />一样,目前<input type="range" />只受 Opera 以及基于 Webkit 的浏览器(如 Chrome 和 Safari)支持。但是关于<input type="range" />有个很酷的事情:像<input type="email" /><input type="URL" /><input type="number" />一样,其他浏览器也支持它!嗯,有点。就像这些标签一样,即使不理解<input type="range" />的浏览器(Firefox,我在看你!)也会默认回到<input type="text" />,所以它仍然有效。太棒了!

另请参阅

Mozilla 的“HTML5 的人”视频系列展示了 HTML5 运动的许多主要声音。作者 Bruce Lawson 非常有趣和权威,尤其是当他批评将 HTML5 用作泛指相关但不同技术的术语时:

“客户和记者将使用’HTML5’来表示 CSS 3/在 iThings 上运行的视频/地理位置启用的应用程序。这是新的’Web 2.0’。但我们从业者需要搞清楚我们的命名。没有 HTML5 图像转换,就像没有 CSS 语义一样-说有这些东西表明你没有理解 2001 年关于分离样式和内容的备忘录。”

阅读并观看完整的采访:hacks.mozilla.org/2011/01/people-of-html5-bruce-lawson

创建搜索字段

HTML5 支持的许多新输入类型之一是search。您有多少次构建了一个使用<input type="text" />的表单,打算允许用户搜索网站?现在我们可以使用更具语义的东西。

如何做…

让我们使用占位属性构建一个快速搜索字段。到目前为止,您已经熟悉了这种过时的方法:

<form>
<input name="something" type="text" value="keyword" />
<input type="submit" value="Search" />
</form>

我们都做过无数次了,对吧?好吧,让我们试试这个:

<form>
<input name="something" type="search" placeholder="keyword" />
<input type="submit" value="Search" />
</form>

发现了区别吗?我们的类型已从text更改为search,占位文本不再使用 value 标记。这对我们开发人员以及搜索引擎和辅助技术更有意义。

它是如何工作的…

指定<input type="search">将在 Opera 以及 Chrome 和 Safari 等基于 Webkit 的浏览器中显示带有圆角的新表单字段:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_05_09.jpg

还有更多…

圆角搜索框是苹果在 OSX 上以及 iPad 和 iPhone 上推广的设计方法。苹果正在逐渐成为移动体验的思想领袖,以及 HTML5 的最积极的倡导者之一。

为什么要修复完美?

当然,可以覆盖新的 HTML5 搜索字段的默认圆角样式,但为什么呢?它已经看起来很酷了!

浏览器支持

这已经成为一个熟悉的叮嘱,但是就像<input type="email" /><input type="URL" /><input type="number" /><input type="range" />一样,您可以放心,如果浏览器不原生理解<input type="search" />,它将继续像<input type="text" />一样进行处理。

搜索结果

新的search规范还支持新的results属性,以在下拉列表中显示已搜索的术语。

另请参阅

别管子弹在nevermindthebullets.com是一个互动在线游戏,专门用来演示微软 Internet Explorer 9 能够处理的 HTML5 和 CSS3 功能,包括:@font-face;<canvas>动画;<header><section>布局;JavaScript 加速;CSS3 2D 变换;CSS3 多背景;可编辑内容;<audio>音轨播放器;<video>播放器。

创建一个选择器来显示日期和时间

每个飞机、火车和汽车租赁网站都将拥有某种时间/日期选择器。终于有了一个语义方法来处理这个问题,所以让我们看看如何使用 HTML5 创建这些input类型。

提示

截至目前,只有 Opera 浏览器完全支持这些新的input标签。

如何做到…

HTML5 实际上有六种不同的新input,可以控制日期和时间。简而言之,它们是:

  • <input type="date" />

  • <input type="datetime" />

  • <input type="datetime-local" />

  • <input type="month" />

  • <input type="time" />

  • <input type="week" />

这些input类型可以被认为是彼此的变体。作为开发人员,我们的工作是选择最适合您收集的数据的那种。

它是如何工作的…

对于日期选择器:

<form>
<input type="date"/>
</form>

对于日期/时间选择器:

<form>
<input type="datetime"/>
</form>

对于本地日期/时间选择器:

<form>
<input type="datetime-local"/>
</form>

对于月/年选择器:

<form>
<input type="month"/>
</form>

对于时间选择器:

<form>
<input type="time"/>
</form>

对于周选择器:

<form>
<input type="week"/>
</form>

还有更多…

鼓励您尝试每个新的基于日历的input标签,以确定哪个最适合您特定的网站或应用程序。

浏览器支持

截至目前,只有 Opera 完全支持这些新的input标签。随着时间的推移,其他浏览器预计会赶上。一旦我们拥有完全可样式化的基于日期/时间的input方法,那将是一个真正快乐的日子。

与此同时,其他浏览器将默认显示这些input类型为纯文本框。它们仍然可以工作,但不会像我们希望的那样漂亮。耐心点,小草 hopper。记住,我们正在处理最新的技术——而不是完全成熟、经过验证和批准的方法。

如果一切都失败了

User Agent Man 撰写了一篇关于当你需要备用计划时该怎么做的文章,当这些各种新的 HTML5 input标签不按你期望的方式工作时。查看完整文章:useragentman.com/blog/2010/07/27/cross-browser-html5-forms-using-modernizr-webforms2-and-html5widgets

另请参阅

Forrst.com是由 Kyle Bragger 使用 HTML5 创建的一个很棒的在线资源。Forrst 是一个充满活力的网络开发者和设计师社区,他们相信通过分享和建设性地批评彼此的工作,可以增加他们对网站创建工艺的知识、技能和热情。我们很欣赏他们的工作态度。

第六章:使用 Canvas 开发丰富的媒体应用程序

在本章中,我们将涵盖:

  • 设置canvas环境

  • 理解 2D 渲染上下文

  • 动态处理形状

  • 使用canvas为图像绘制边框

  • 圆角

  • 创建交互式可视化

  • 弹跳球

  • 创建备用内容

介绍

“我更喜欢画画而不是说话。画画更快,也给谎言留下的空间更少。”- 勒·柯布西耶

这可能是整本书中最实验性的一章。在接下来的配方中,我们将真正推动这组配方所能实现的极限。

注意

请注意,随着时间的推移,实验性的新canvas元素规范可能会发生变化。请将这组配方视为出版时可能的情况的快照。

在网站上放置一张图片是如此容易,我们现在认为这是理所当然的。通过代码,你只需告诉浏览器显示一张图片,就完成了。所有这些似乎都像是小孩子的游戏。目前,一些浏览器实际上可以使用新的canvas元素动态创建图像。所有繁重的工作都交给了 JavaScript。

新的开源canvas元素的很酷之处不仅在于你可以动态地创建图像,而且用户的操作也可以实时地创建新的图像,而无需插件。听起来很棒,对吧?在许多方面确实如此,但它也让我们使用辅助技术的朋友们感到束手无策。

提示

如果你使用的浏览器不支持新的canvas元素会发生什么?基本上什么都不会发生。浏览器只是不会显示它。这就是为什么你需要特别小心这项技术,不要在新的canvas元素中放置任何你的网站或应用程序绝对依赖的东西。你还必须考虑备用内容。

支持canvas的浏览器包括:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_01.jpg

提示

在继续使用新的canvas元素进行开发之前,请确保你对 HTML 和 JavaScript 有扎实的基础。对面向对象编程感到舒适肯定也是有好处的。

在本章中,我们将看到设置canvas环境的真实例子,理解 2D 渲染上下文,动态处理形状,使用canvas为图像绘制边框,圆角,创建交互式可视化,弹跳球以及创建备用内容。

现在,让我们开始吧!

设置canvas环境

创建新的canvas元素很容易。

如何做…

看看这是多么简单:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="FirstCanvas" width="800" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

它是如何工作的…

当然,我们可以使用任何需要的高度和宽度尺寸,但是我们需要开始的是这组简单的标签。

提示

你可能会认为我们可以使用 CSS 来控制高度和宽度,但要抵制这种诱惑。因为新的canvas元素包含一个 2D 渲染上下文,这种方法可能会导致不可预测的行为。

还有更多…

接下来,我们将调用新的canvas元素 JavaScript API,同时调用 jQuery:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("FirstCanvas");
var ctx = canvas.getContext("2d");
});
</script>
</head>
<body>
<canvas id="FirstCanvas" width="800" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

他很聪明

“让我完全明确一件事:当你使用canvas时,你并不是在canvas元素本身上绘图。相反,你实际上是在通过 JavaScript API 访问canvas元素的 2D 渲染上下文上绘图。”- Rob Hawkes

我在说什么?

苹果最早在 OSX Dashboard 中引入了新的canvas元素。后来它在 Safari 和 Chrome 等 web 浏览器中实现,其他浏览器也纷纷效仿。从那时起,它已成为 HTML5 规范的正式部分。

<canvas>的下一步是什么?

现在,我们只是勉强触及了新的canvas元素所能做到的一小部分。现在和将来,我们将使用它来创建动画,图表,图表,绘图应用程序,图形和用户界面。你会想到什么呢?

另请参阅

开发者 Martin Angelov 为 Tutorial Zine 撰写了一篇名为《使用 Canvas 和 jQuery 创建 HTML5 幻灯片》的很棒的指南:tutorialzine.com/2010/09/html5-canvas-slideshow-jquery。在这篇文章中,Martin 演示了如何将新的 canvas 元素与 jQuery 结合使用,这是最流行的 JavaScript 框架,以创建一个非常互动的图像幻灯片。

理解 2d 渲染上下文

重要的是要理解,新的canvas元素实际上是一个在浏览器中绘制位图图像的“表面”。

如何做…

像这样定义一个canvas标签只是讲了一半的故事:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="FirstCanvas" width="800" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

它是如何工作的…

单独的 HTML5 代码什么也做不了。我们必须使用 JavaScript 来使文档对象模型检索 2d 渲染上下文,以便让一些事情发生:

<script>
$(document).ready(function() {
var canvas = document.getElementById("FirstCanvas");
var ctx = canvas.getContext("2d");
});
</script>

公平地说,如果 HTML 中没有canvas标签,那么这一点 JavaScript 也不会起作用。

还有更多…

你可能会想到这个名字。如果有一个 2d 渲染上下文,那么可能也有一个 3d 渲染上下文吧?简短的答案是肯定的。但更详细的答案并不那么简单。

虽然在理论上存在 3d 渲染上下文,但在本出版物发表时,没有浏览器支持它。所以如果新的canvas元素以 3d 方式渲染,但没有人看到它,它真的做了什么吗?

你可以掌握

2d 上下文为新的canvas元素使用了许多不同的绘图上下文,这些语法应该对熟悉 CSS 和 JavaScript 的人来说看起来非常熟悉。

X,见 Y

在绘制时,请记住浏览器窗口左上角的 X 和 Y 轴。数值向下增加。

尊重我的权威!

万维网联盟的 HTML5Canvas 2d 上下文规范可以在这里找到:dev.w3.org/html5/2dcontext。在那里,我们可以深入了解诸如符合性要求、canvas状态、变换、合成、颜色和样式、线条样式、阴影、简单形状、复杂形状、焦点管理、文本、图像、像素操作、绘图模型、示例等更多信息。

另请参阅

Steve Fulton 和 Jeff Fulton 为 O’Reilly Books 撰写了《HTML5 Canvas》一书。虽然本章将为您提供大约 30 页有价值的新canvas元素配方,但 Fulton 的书大约有 400 页。把它当作是本章结束后的资源。在这里查看:oreilly.com/catalog/0636920013327

动态处理形状

让我们来看看允许新的canvas元素绘制矩形的 JavaScript 函数。

如何做…

fillRect(x,y,width,height)
strokeRect(x,y,width,height)

按顺序:

fillRect(x,y,width,height)

画一个填充的矩形。接下来,

strokeRect(x,y,width,height)

在矩形周围画出一个轮廓。

现在,让我们画一些形状。

它是如何工作…

我们将从我们的基本canvas代码开始,并整合我们的新函数:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("FirstCanvas");
var ctx = canvas.getContext("2d");
ctx.strokeRect(10, 10, 396, 236);
ctx.fillStyle = "red";
ctx.fillRect(11, 11, 100, 100);
ctx.fillStyle = "white";
ctx.fillRect(111, 11, 34, 100);
ctx.fillStyle = "red";
ctx.fillRect(156, 11, 249, 100);
ctx.fillStyle = "white";
ctx.fillRect(11, 111, 394, 34);
ctx.fillStyle = "red";
ctx.fillRect(11, 145, 100, 100);
ctx.fillStyle = "white";
ctx.fillRect(111, 145, 34, 100);
ctx.fillStyle = "red";
ctx.fillRect(156, 145, 249, 100);
});
</script>
</head>
<body>
<canvas id="FirstCanvas" width="416" height="256">
<p>Flag of Denmark</p>
</canvas>
</body>
</html>

我们创建的东西类似于丹麦的国旗!

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_02.jpg

还有更多…

这个例子一开始可能并不令人印象深刻,但当你记住我们几乎没有使用任何 HTML 和 CSS 就创建了一张图片时,新的canvas元素开始看起来相当令人印象深刻。

任何你想要的方式

请注意,虽然我们使用了颜色名称(“white”和“red”),我们也可以使用十六进制值或 RGB 甚至 HSL!使用对你和你的互动项目最有意义的内容。

类似于表格?

将此示例的颜色和大小规格几乎视为我们过去用于布局的老式tables。虽然肯定不同,但在这种情况下确实有一些相似之处。

首先成为一个正方形

掌握矩形是在掌握设置元素本身的能力之后,重要的第一个canvas技术。理解这种方法的基础将帮助你掌握接下来几个配方的基础。

另请参阅

另一本将近 400 页的书是 Rob Hawkes 的《Foundation HTML5 Canvas: For Games and Entertainment》,来自 Friends of Ed。在这本书中,Hawkes 为那些刚接触新的“画布”元素的人,一直到最有经验的专家提供了一个提升技能的出版物。听起来像你认识的人吗?在这里查看:friendsofed.com/book.html?isbn=1430232919

使用画布为图像绘制边框

让我们仔细看看使用新的“画布”元素绘制图像周围边框的超级简单方法。

如何做…

首先,我们将从基本的“画布”代码开始,并添加一行新的代码来绘制边框:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("FirstCanvas");
var ctx = canvas.getContext("2d");
ctx.strokeRect(10, 20, 100, 100);
});
</script>
</head>
<body>
<canvas id="FirstCanvas" width="800" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_03.jpg

它是如何工作的…

JavaScript 的那一行告诉浏览器创建一个矩形,从新的“画布”元素的左边 10 像素,顶部 20 像素开始。它绘制了一个 100 像素的正方形框。

还有更多…

这很好,但如果我们希望边框是除了默认颜色之外的任何其他颜色,我们需要指定它:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "rgb(0, 128, 0)";
ctx.strokeRect(10, 20, 100, 100);
});
</script>
</head>
<body>
<canvas id="myCanvas" width="600" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

在这种情况下,我们使用strokeStyle来指定纯绿色的 RGB 颜色。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_04.jpg

首先是样式

提示

如果你打算为边框设置样式,你需要在浏览器绘制边框之前指定。如果你在之后指定样式,浏览器将会忽略它。

许多颜色值都可以使用

我们刚刚使用的样式属性是 RGB,但该方法也适用于颜色(例如“绿色”)、十六进制值、HSL 和 RGBA。

我喜欢大边框,我无法否认

如果没有指定边框宽度,浏览器将自动绘制一个像素的边框。以下是如何更改它的方法:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth = 10;
ctx.strokeStyle = "rgb(0, 128, 0)";
ctx.strokeRect(10, 20, 100, 100);
});
</script>
</head>
<body>
<canvas id="myCanvas" width="600" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

就是这么简单:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_05.jpg

另请参阅

rgraph.net是一个专门为新的“画布”元素设计的图形库。它允许您轻松创建各种图表类型:条形图、双极图、圆环图、漏斗图、甘特图、水平条形图、LED 显示、折线图、仪表、里程表、饼图、进度条、玫瑰图、散点图和传统的雷达图,使用 HTML5、canvas和 JavaScript。

圆角

到目前为止,我们已经使用方形或矩形形状创建了图像和边框。接下来,我们将看看如何使用新的“画布”元素通过 JavaScript 来使这些图像和边框的角变圆。

如何做…

圆角的能力不是canvas的本机功能,但 Rob Hawkes 是一个非常聪明的人,他想出了如何实现它的方法。这就是 Rob 做的事情,在这里解释:rawkes.com/blog/2010/12/11/rounded-corners-in-html5-canvas.

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
$(document).ready(function() {
var canvas = $("#myCanvas");
var context = canvas.get(0).getContext("2d");
var rectX = 10;
var rectY = 10;
var rectWidth = 100;
var rectHeight = 100;
var cornerRadius = 15;
context.lineJoin = "round";
context.lineWidth = cornerRadius;
context.strokeStyle = "rgb(0, 128, 0)";
context.strokeRect(rectX+(cornerRadius/2), rectY+(cornerRadius/2), rectWidth-cornerRadius, rectHeight-cornerRadius);
});
</script>
</head>
<body>
<canvas id="myCanvas" width="600" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

它是如何工作的…

首先,Rob 选择了一个稍微不同的方法来调用 2d“画布”渲染上下文,但他的方法也完全有效。看看:

$(document).ready(function() {
var canvas = $("#myCanvas");
var context = canvas.get(0).getContext("2d");

Rob 代码的下一部分应该看起来非常熟悉:他设置了图像的 X 和 Y 坐标,它的大小,然后是边框半径:

var rectX = 10;
var rectY = 10;
var rectWidth = 100;
var rectHeight = 100;
var cornerRadius = 15;

然后 Rob 调用了连接线和他想要使用的特定边框半径的能力。假装直到你成功为止!

context.lineJoin = "round";
context.lineWidth = cornerRadius;

最后是边框的颜色(仍然是绿色!)和将所有内容联系在一起的最后一小部分脚本:

context.strokeStyle = "rgb(0, 128, 0)";
context.strokeRect(rectX+(cornerRadius/2), rectY+(cornerRadius/2), rectWidth-cornerRadius, rectHeight-cornerRadius);

还有更多…

现在 Rob-如果你也在跟着做-可以成为一个拥有美丽圆角图像的摇滚明星。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_06.jpg

就像学术能力测试一样

提示

记住:lineWidth对于新的“画布”元素来说就像 border-radius 对 CSS 来说一样。它们都实现了同样的功能-但是方式完全不同。

IE 呢?

可以使用 ExplorerCanvas 库在 Internet Explorer 6-8 中支持一些新的“画布”元素的功能:code.google.com/p/explorercanvas.

我们正在奠定基础

在本章的大部分食谱中,我们只使用了新的canvas元素在浏览器中绘制静态形状,而没有使用图像。这可能看起来毫无事件,甚至可能违反直觉。重点是为您提供这种新能力的坚实基础,以便您可以扩展它,使用新的canvas元素创建游戏,可视化数据,并允许用户动态绘制对象。

另请参阅

Mozilla 的“HTML5 的人”视频系列中有许多 HTML5 运动的领军人物。John Foliot 是 HTML5 中媒体元素无障碍子委员会的联合主席。当他为这些技术当前浏览器支持的状况感到懊恼时,这一点应该不足为奇:

“我认为 HTML5 开始提供的许多东西对所有用户都有好处,包括使用辅助技术的用户。然而,许多承诺的东西在所有浏览器中尚不受支持,相关技术——辅助技术——还有很长的路要走才能利用这一好处。”

阅读并观看完整的采访:hacks.mozilla.org/2011/02/people-of-html5-john-foliot.

创建交互式可视化

Carbon Five 团队面临着一个艰巨的任务:创建他们的技能和兴趣的物理图。他们可能从办公室的墙开始,但很快意识到新的canvas元素带来的新能力将允许交互性,并且可以根据此进行结论。以下是他们在这里所做的:carbonfive.github.com/html5-playground/interest-map/interest-map.html.

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_07.jpg

如何做…

提示

在按照本食谱操作时,查看源代码将非常有帮助:view-source:http://carbonfive.github.com/html5-playground/interest-map/interest-map.html

Carbon Five 团队提醒我们,画布并不是 HTML5 规范的正式部分,他们使用 HTML4.01 Transitional DOCTYPE 创建了这个交互式可视化。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

以下是他们在 JavaScript 和新的canvas元素中所做的一些详细内容。他们从一些变量开始,比如卡片样式。在这里,他们做了几件事情:设置背景颜色,创建黑色边框,卡片的宽度,以及围绕它的阴影的值。

var CARD_STYLE = { fill:'rgb(240,240,240)',stroke:'rgb(0,0,0)',width:.05, shadow:{x:0, y:4, blur:4, color:'rgba(0, 0, 0, 0.3)'} };

下一个变量对于了解 CSS 的人来说应该很熟悉。在这里,设置了卡片的字体重量、大小、字体、颜色等等:

var CARD_FONT = {font:'bold 8pt Courier', color:'#555', yoffset:10, height:14};

接下来,他们设置了与边距、宽度、高度、比例、半径、阴影等相关的几个变量。

var MARGIN = [75,75,75,100], WIDTH = 1000-MARGIN[1]-MARGIN[3], HEIGHT = 650-MARGIN[0]-MARGIN[2], CARD_SCALE=.75, CARD_RADIUS = 40, TAG_RADIUS = 50, CACHE_RADIUS=70, CLEAR_RADIUS = 50, ITERATIONS = 20, DEGREE = .5, CARD_SHADOW = 2, AXIS_ANIM=700;

最后,他们为技能、人员和人员与技能矩阵设置了变量。不幸的是,这些代码块太长,无法在此重新发布。

它是如何工作的…

变量本身并不会有太大作用,除非它们有函数来对其进行操作。

在初始化显示后,Carbon Five 团队使用更多的函数,比如在 2Dcanvas渲染元素上绘制:

function draw(t) {
var ctx = el('display').getContext('2d');
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.save(); ctx.globalAlpha = 1 - .75*arrow_visibility;
each( cards, function(card) {
var t0=card.tween(t); x = MARGIN[3] + card.lx + (card.x-card.lx)*t0, y = MARGIN[0] + card.ly + (card.y-card.ly)*t0;
draw_card( ctx, x, y, card.index);
});
ctx.restore();
if ( arrow_visibility > 0 ) {
ctx.save(); ctx.globalAlpha = arrow_visibility;
each( PEOPLE, function(p) { draw_interest_arrow(ctx,p,t); });
ctx.restore();
if (over_person) draw_over_arrow(ctx,over_person,t);
}
draw_axes(ctx);
}

以及创建名称标签:

function nametag( ctx, cardx, cardy, person, r, interest ) {
ctx.save(); ctx.translate( cardx, cardy ); ctx.rotate( r + .4*(Math.random()-.5) );
ctx.translate( -TAG_RADIUS - + 4*Math.random(), 0 ); ctx.rotate( -r );
draw_nametag( ctx, person, interest );
ctx.restore();
}

并绘制箭头:

function draw_arrow( ctx, length, head_length, head_width ) {
var cx1 = .9*(length - head_length), cy1 = .2*head_width, cx2 = (length - head_length), cy2=.2*head_width;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.bezierCurveTo( cx1, cy1, cx2, cy2, length-head_length, head_width );
ctx.lineTo( length, 0 ); ctx.lineTo( length-head_length, -head_width );
ctx.bezierCurveTo( cx2, -cy2, cx1, -cy1, 0, 0 );
ctx.closePath();
}

还有更多…

已经设置了变量和函数,最后要做的就是在 HTML 中调用canvas元素本身,为其提供一个运行的空间:

<canvas id="display" width="1000" height="650"></canvas>

两个出租人的邪恶

在旧网页时代,Carbon Five 团队可以选择将他们的地图放在物理墙上,或者为计算机显示创建静态图像。虽然任何一种方式都可以渲染得和使用新的canvas元素一样好,但它们都不允许团队像新的canvas元素那样提取有价值的信息。

备用内容呢?

有趣的是,Carbon Five 在这种情况下没有在新的“画布”元素中使用任何回退内容。这是一个你需要仔细权衡的方法,因为那些使用旧浏览器或辅助技术的人将什么也看不到,真的什么也看不到。Carbon Five 在这个内部项目中得以成功。你能吗?

接受他的提议。

blog.carbonfive.com/2011/02/17/visualizing-skillsets-in-html5-canvas-part-1上写关于这个项目时,Carbon Five 的开发者亚历克斯·克鲁克山甚至提出为前五个以合理格式提供数据的人创建可视化地图。截至发布日期,尚不清楚是否有人接受了他的提议。

另请参阅

雅各布·赛德林用他的新画布元素可视化了乐队 Radiohead 的歌曲“Idioteque”,这首歌来自专辑“Kid A”,网址是:nihilogic.dk/labs/canvas_music_visualization。雅各布正在挑战“画布”元素和 JavaScript 的极限,这就是为什么我们认为他很棒!

弹跳一个球

我们已经看过如何使用新的“画布”元素绘制形状,接下来我们将把注意力转向让这些形状移动起来。作者文森·鲁弗斯向我们展示了如何做到这一点。

如何做…

我们将从我们通常的canvas HTML 代码开始:

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="FirstCanvas" width="800" height="600">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

接下来是独特的部分:JavaScript。在这里,文森选择了一个稍微不同的方法来调用 2D“画布”渲染上下文,但他的方法也完全有效。看看:

<script>
var context;
function init()
{
context= myCanvas.getContext('2d');
context.beginPath();
context.fillStyle="#0000ff";
// Draws a circle of radius 20 at the coordinates 100, 100 on the canvas
context.arc(100,100,20,0,Math.PI*2,true); context.closePath();
context.fill();
}
</script>

将这些代码放在一起,应该是这样的。请注意,添加了一个onLoad函数到body标签。

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
var context;
function init()
{
context= myCanvas.getContext('2d');
context.beginPath();
context.fillStyle="#0000ff";
// Draws a circle of radius 20 at the coordinates 100, 100 on the canvas
context.arc(100,100,20,0,Math.PI*2,true); context.closePath();
context.fill();
}
</script>
</head>
<body onLoad="init();">
<canvas id="myCanvas" width="300" height="300">
<!-- Fallback code goes here -->
</canvas>
</body>
</html>

然后渲染这个蓝色的球:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_08.jpg

它是如何工作的…

到目前为止,文森的代码非常简单。我们看到他是如何调用 2D“画布”渲染上下文的。接下来他设置了填充的颜色:

context.fillStyle="#0000ff";

然后画一个距离顶部和左边 100 像素的弧线,并用他已经设置的蓝色填充它:

context.arc(100,100,20,0,Math.PI*2,true); context.closePath();
context.fill();

但现在我们只有一个蓝色的球静静地坐在那里。接下来,文森向我们展示了如何使用变量和一个名为draw的新函数让它移动。

还有更多…

<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<meta charset="utf-8" />
<script src="img/ jquery.min.js"></script>
<script>
var context;var x=100;var y=200;var dx=5;var dy=5;
function init()
{
context= myCanvas.getContext('2d');
setInterval(draw,10);
}
function draw()
{
context.beginPath();
context.fillStyle="#0000ff";
// Draws a circle of radius 20 at the coordinates 100, 100 on the canvas
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
x+=dx;
y+=dy;
}
</script>
</head>
<body onLoad="init();">
<canvas id="myCanvas" width="300" height="300" >
</canvas>
</body>
</html>

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_09.jpg

正如你所看到的,球在运动,但只是画了一条直线超出了“画布”的边缘。文森解释了原因:

“这是因为每次调用draw()函数时,它都会在新的坐标处画一个圆圈,而不会移除旧的圆圈。这就是getContext对象的工作原理,所以这不是一个 bug;它实际上并没有移动圆圈,而是每次调用函数时在新的坐标处画一个圆圈。”

重新开始

文森向我们展示了一种方法,可以在新的“画布”元素绘制每一个新的圆圈时擦除旧的圆圈:

<script>
var context;
var x=100;
var y=200;
var dx=5;
var dy=5;
function init()
{
context= myCanvas.getContext('2d');
setInterval(draw,10);
}
function draw()
{
context.clearRect(0,0, 300,300);
context.beginPath();
context.fillStyle="#0000ff";
// Draws a circle of radius 20 at the coordinates 100, 100 on the canvas
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
x+=dx;
y+=dy;
}
</script>

现在,球似乎向右下方超出了“画布”的边界。

不要把我困住

为了确保球保持在“画布”的边界内,文森编写了一些逻辑来检查 x 和 y 坐标是否超出了“画布”的尺寸。如果超出了,他就让球改变方向。

<script>
var context;
var x=100;
var y=200;
var dx=5;
var dy=5;
function init()
{
context= myCanvas.getContext('2d');
setInterval(draw,10);
}
function draw()
{
context.clearRect(0,0, 300,300);
context.beginPath();
context.fillStyle="#0000ff";
// Draws a circle of radius 20 at the coordinates 100, 100 on the canvas
context.arc(x,y,20,0,Math.PI*2,true);
context.closePath();
context.fill();
// Boundary Logic
if( x<0 || x>300) dx=-dx;if( y<0 || y>300) dy=-dy;x+=dx;y+=dy;
}
</script>

现在,球应该在“画布”的四个边上不断地弹跳。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_06_10.jpg

这是一个成长的过程

正如文森在他引人入胜的教程中提醒我们的那样,弹跳的球乍看起来可能很简单,但实际上这是一个关键的技术,需要理解才能开发任何新的 HTML5“画布”元素游戏。

另请参阅

可以在 Yuri Vishnevsky 的weavesilk.com上看到用户生成的图形的一个美丽的例子。该网站使用新的canvas元素作为生成艺术实验的一部分。一些生成的图像非常漂亮,Yuri 已经将它们作为令人惊叹的桌面背景图像提供。还计划推出 iPhone 和 iPad 版本。

创建回退内容

“当作者使用canvas元素时,他们还必须提供内容,当呈现给用户时,传达与位图canvas本质上相同的功能或目的。此内容可以放置为canvas元素的内容。canvas元素的内容(如果有)是元素的回退内容。”- WHATWG HTML5 规范

如果有人查看您的精彩新canvas应用程序的浏览器使用较旧的浏览器,并且无法识别您的编码天赋会发生什么?或者当有人使用辅助技术时会发生什么?让我们来看看。

如何做到…

如果出于某种原因,用户的浏览器不支持新的canvas元素,作为开发人员,我们要为他们提供有价值的东西。

在这里我们可以使用图像作为回退。

<canvas id="clock" width="200" height="200">
<img src="img/clock.gif" width="200" height="200" alt="clock"/>
</canvas>

或者文本:

<canvas id="clock" width="200" height="200">
<p>clock</p>
</canvas>

或者几乎任何其他元素。

它是如何工作的…

到目前为止,您已经熟悉了alt标签如何用于图像文件:如果图像文件不显示或用户依赖辅助技术,alt标签至少为他们提供了一个有价值的文本标签,代表他们所错过的内容。新的canvas元素的回退内容是一个类似的概念,但它能够做到并且比只是一个alt标签更有价值。

还有更多…

支持新的canvas元素的浏览器将忽略容器内的内容,并正常呈现新的canvas元素。

谢谢,Mozilla

如果需要回退内容,必须使用一些 CSS 技巧来掩盖 Safari 中的回退内容(应该只呈现canvas),并且还要掩盖 IE 中的 CSS 技巧本身(应该呈现回退内容)。- Mozilla.org

我们将如何处理可访问性?

规范作者和 HTML5 社区普遍认为新的canvas元素只是部分成熟。让使用辅助技术的人置身于寒冷中似乎不是正确的做法。敬请关注。

我们准备好使用了吗?

许多开发人员认为新的canvas元素的可访问性是新 HTML5 规范中的最后一个关键点。由于几乎没有有意义的回退功能,这个新元素似乎还没有准备好投入使用。

第七章:使用 JavaScript 进行交互

在本章中,我们将涵盖:

  • 使用 JavaScript 播放音频文件

  • 使用拖放 API 与文本

  • 使用vid.ly和 jQuery 实现跨浏览器视频支持

  • 使用 jQuery 动态显示视频

  • 使用 jQuery 创建可移动的视频广告

  • 使用Easel.jscanvas标签控制图像的显示

  • 使用Easel.jscanvas标签来制作图像序列的动画

  • 使用canvas标签和 JavaScript 进行随机动画播放音频

介绍

虽然 HTML5 可能会结束对 Flash 的使用,但它使 JavaScript 比以前更受欢迎。有许多库和插件可用于增强和扩展 HTML5 和 CSS3,以创建丰富的交互体验。

本章包含了一些示例,展示了 JavaScript 如何与 HTML5 标签一起使用,例如音频、视频和画布,以及 CSS3 选择器和元素。

使用 JavaScript 播放音频文件

HTML5 在互联网上使用音频文件方面引入了更多的灵活性。在这个示例中,我们将创建一个游戏来练习使用音频标签和 JavaScript 加载和播放声音。

准备工作

您需要一个音频文件来播放,一张图片和一个支持 HTML5 的现代浏览器。本章的示例文件可以从www.packtpub.com/support?nid=7940下载。Free Sound Project (freesound.org)有您可以使用的音频文件,只要给予制作人信用,照片可以在www.Morguefile.com找到,用于您的个人项目。

如何做…

现在我们准备创建一系列按钮和一个简短的 JavaScript 程序,当其中一个按钮被按下时,将播放一个随机的音频文件。

打开您的 HTML 编辑器并创建一个 HTML5 页面的开头部分。

<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Playing a sound file with JavaScript</title>

因为我们只有几种样式,所以我们将它们添加到 HTML 页面的头部区域。

<style>h1{font-family:"Comic Sans MS", cursive; font-size:large; font-weight:bold;}
button{ padding:5px;margin:5px;}
button.crosshair { cursor: crosshair; }
button.crosshairthree {margin-left:40px;
cursor:crosshair;} </style>

脚本需要创建三个变量。开头的脚本标签和变量应该看起来像以下代码块:

<script>//variables
var mySounds=new Array();
mySounds[0]="boing";
mySounds[1]="impact";
mySounds[2]="squeak";
mySounds[3]="whack";
mySounds[4]="space";
var soundElements;
var soundChoice;

现在我们已经为脚本创建了全局变量,我们可以创建函数。键入function whackmole(){开始函数,然后在新行上键入var i = Math.floor(Math.random() * 5);使用 JavaScript 数学库生成一个相对随机的数字。接下来,键入soundChoice = mySounds[i];将数组值分配给soundChoice。使用soundElements[soundChoice].play();}关闭函数。您的函数代码目前应该看起来像以下内容:

function whackmole() {
var i = Math.floor(Math.random() *5);
soundChoice = mySounds[i];
soundElements[soundChoice].play();}

键入function init(){开始函数。在新行上,键入soundElements = document.getElementsByTagName("audio");} </script>来完成我们的 JavaScript 代码块。它应该看起来像以下代码块:

function init(){
soundElements = document.getElementsByTagName("audio");}
</script>

关闭头标签并键入 body 标签,添加一个init()函数调用,使其看起来像:

</head><body onLoad="init();">

使用<header>标签为页面的页眉区域创建一个标题区域。使用标题标签<h1>显示页面的标题:

<header><h1>Whack A Mole!</h1></header>

有五个按钮来创建一个平衡的外观,它们都被分配了一个类。

<section> <p> <button class="crosshair" onclick="whackmole();"> <img src="img/downmole.png" width="37" height="24" alt="Mole peeping out of hole"></button>
<button class="crosshair" onclick="whackmole();"> <img src="img/downmole.png" width="37" height="24" alt="Mole peeping out of hole"></button></p>

第三个按钮的类名为crosshairthree,以便更好地控制其在屏幕上的位置。

<p style="padding-left:30px;"><button class="crosshair" onclick="whackmole();"><img src="img/downmole.png" width="37" height="24" alt="Mole peeping out of hole"></button></p> <p><button class="crosshair" onclick="whackmole();"> <img src="img/downmole.png" width="37" height="24" alt="Mole peeping out of hole"></button><button class="crosshair" onclick="whackmole();"><img src="img/downmole.png" width="37" height="24" alt="Mole peeping out of hole"></button></p></section>

如果您正在使用本书的代码文件,那么音频文件标签应该类似于下面的代码块:

<section><audio id ="boing" autobuffer>
<source src="img/cartoonboing.ogg" />
<source src="img/cartoonboing.mp3" /></audio>
<audio id ="impact" autobuffer>
<source src="img/cartoonimpact.ogg" />
<source src="img/cartoonimpact.mp3" /></audio>
<audio id ="squeak" autobuffer>
<source src="img/cartoonsqueak.ogg" />
<source src="img/cartoonsqueak.mp3" /></audio>
<audio id ="whack" autobuffer>
<source src="img/cartoonwhack.ogg" />
<source src="img/cartoonwhack.mp3" /></audio>
<audio id="space" autobuffer>
<source src="img/cartoonspaceboing.ogg" />
<source src="img/cartoonspaceboing.mp3" /></audio>

用关闭标签完成页面:

</section></body></html>

将文件保存为playing-audio-files-with-javascript.html并在浏览器中查看。它应该看起来类似于以下屏幕截图:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_01.jpg

它是如何工作的…

首先,我们创建了一个基本的 HTML5 页面的开头。然后,我们添加了 CSS 样式,为按钮添加背景图像,并在鼠标或指针设备移动到按钮上时将鼠标图标更改为十字准线。这给了我们一个视觉上的模拟目标武器,比默认的鼠标图标更有趣。

创建了三个变量供脚本使用:mySounds, soundElementssoundch。我们创建的第一个函数名为whackmole()包含一个内部变量i,它保存了一个随机生成的数字的结果。Math.random()导致生成一个伪随机数。然后我们将其乘以5,我们的音频文件数量,并使用Math.floor()的结果创建一个值范围从零到五的整数。然后将该值分配给临时变量i,然后用于使用随机生成的数组值填充变量mySounds。这个新的数组值存储在变量soundChoice中,soundChoice = mySounds[i]。这使我们能够在按下按钮时使用soundElements[soundChoice].play()触发audio标签的play()动作。

我们创建的第二个函数是init(),稍后我们将其与body标签绑定,使用onLoad,这样我们就可以使用audio标签及其数组值,通过getElementsByTagName获取音频文件,如soundElements变量中所包含的。

接下来,我们添加了<body onLoad="init();">标签,以及一系列包含我们可爱的鼹鼠图像的按钮到页面上。每个按钮都包含一个onClick()事件,调用了whackmole()函数。我们的第三个按钮与其他按钮的类不同,crosshairthree,它在按钮左侧添加了额外的边距,使其看起来更加居中。

注意

火狐目前有一个怪癖,如果你不先列出.ogg音频源,它就找不到。

最后,我们使用<audio><source>标签将声音文件添加到页面。使用源标签列出了每个文件的oggmp3格式。因为源标签被认为是其所包围的父音频标签的“子”标签,所以根据使用的浏览器,任何文件格式都会播放,因为不同的浏览器目前更喜欢不同的声音文件格式。

还有更多…

您可以看到,通过为不同的图像播放不同的声音文件,非常容易创建一个儿童的形状或动物朗读页面等应用程序。

使用 jQuery 控制音频剪辑的外观

jQuery 中的.animate函数打开了新的方式,当访问者采取行动或作为丰富媒体体验的一部分时,可以使音频控件出现、淡出和消失。以下是一个示例,演示了如何使音频控件淡出,然后迅速重新出现:

<script> $(document).ready(function(){
$('audio').delay(500).hide('fade', {}, 1000 ).slideDown('fast'); }); </script>
<!- - the HTML -- ><audio id ="boing" autobuffer> <source src="img/cartoonboing.ogg" /> <source src="img/cartoonboing.mp3" /></audio>

我们将在本章的一个示例中使用视频文件执行类似的技巧。

另请参阅

第八章,“拥抱音频和视频”将涵盖更多关于音频标签及其使用方式的信息。

使用文本的拖放 API

虽然所有浏览器都可以原生地拖放图像或链接,但放置对象以前需要复杂的 JavaScript 或第三方库。拖放 API 旨在提供一种更简单、标准化的方式,使用户能够将任何类型的对象拖放到标识区域中。实际上,在各种浏览器中使用该 API 是一项挑战。目前主要支持此 API 的浏览器是 Firefox、Chrome 和 Safari。

准备工作

www.packtpub.com/support?nid=7940下载本教程的代码。本教程标题中使用的字体来自www.fontsquirrel.com,您也可以在该网站下载其他字体。本教程可能无法在 Internet Explorer 中使用。我们将创建一个井字棋游戏,演示拖放 API 的工作原理。

如何做…

打开您的 HTML 编辑器,首先创建一个基本的 HTML5 页面。我们将添加两个样式表链接,一个用于支持我们将加载到页面标题的@fontface字体,另一个是我们的主样式表。输入如下所示的代码,然后将文件保存为using-drag-drop-api.html

<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <title>Using the drag-and-drop API element</title> <link rel="stylesheet" href="fonts/specimen_files/specimen_stylesheet.css" type="text/css" charset="utf-8" /> <link rel="stylesheet" href="stylesheet.css" type="text/css" charset="utf-8" />

让我们继续对页面进行样式设置。创建或打开名为stylesheet.css的 CSS 文件。将页面的整体margin设置为100px,默认颜色设置为#666

@charset "UTF-8";/* CSS Document */body { margin:100px; color:#666; }

页面的内容标签应该都设置为display:block,如下所示的代码:

article, aside, figure, footer, header, hgroup, menu, nav, section { display:block; }

现在,我们要指定@fontface信息。代码和字体文件来自www.fontsquirrel.com字体包,已包含在本教程的代码文件中。

@font-face { /* This declaration targets Internet Explorer */ font- family: '3DumbRegular';src: url('3dumb-webfont.eot');}@font-face {/* This declaration targets everything else */font-family: '3DumbRegular';src: url(//:) format('no404'), url('fonts/3dumb- webfont.woff') format('woff'), url('fonts/3dumb-webfont.ttf') format('truetype'), url('fonts/3dumb-webfont.svg#webfontlNpyKhxD') format('svg');font-weight: normal;font-style: normal;}

h1标签添加颜色,并将font-family属性设置为3DumbRegular,这是我们字体的名称。

h1{color:#C60;font-family: '3DumbRegular';}

创建一个名为gametilebox的新 div,用于容纳组成游戏瓷砖的字母。将盒子的float属性设置为left,宽度和高度设置为280px。根据以下代码片段设置padding, margin-right, borderbackground-color

#gametilebox{ float:left;width:280px; height:280px; padding:10px; margin-right:30px; border:1px solid #000; background-color:#ccc; }

游戏板将共享许多与瓷砖框相同的属性,因此复制gametilebox的样式,然后粘贴并命名为"gameboard"。添加一个background-image属性,url 为images/tictactoegrid.jpg,并将background-color设置为aa

gameboard div应该如下所示代码:

#gameboard { float:left; width:280px; height:280px; padding:10px; margin-right:30px;border:1px solid #000; background-image:url(images/tictactoegrid.jpg); background-color:#aaa;}

让我们对div块进行样式设置,用于放置我们的字母。所有block div 的float应设置为leftwidth不应大于85pxheight不应大于80px。它们将位于 3x3 的网格上,因此第二行和第三行的第一个块也需要具有clear:both属性。第二行和第三行的第三个块应该具有较低或没有paddingmargin-right属性。因为有九个,所以这里只显示了一个块代码的示例:

#blockA {float:left; width:75px; height:75px; padding:5px 5px 5px 2px; margin-right:10px; border:none; background-color:red;}
#blockB {float:left; width:75px; height:75px; padding:5px; margin-right:10px; border:none; background-color:blue;}

现在,我们将为字母游戏瓷砖设置样式。在样式表中创建一个名为lettertile的新类,然后按照这里显示的属性设置类的属性:

.lettertile { width:60px; height:60px; padding:5px; margin:5px; text-align:center; font-weight:bold;font-size:36px;color:#930; background-color:transparent;display:inline-block;}

我们将添加的最后一个样式是draggable属性。创建下面的样式以帮助跨浏览器兼容性:

*[draggable=true] { -moz-user-select:none; -khtml-user-drag: element; cursor: move;}

样式表已经完成,现在我们可以开始编写脚本来拖动字母瓷砖并放置它们。

打开之前创建的 html 页面using-drag-drop-api.html,并为 IE 浏览器输入以下代码:

<!--[if IE]><script src="img/html5.js"> </script><![endif]-->

在样式表链接的下方直接添加一个开头的<script>标签,并输入第一个函数dragDefine(ev),该函数接受一个事件参数,并在后面加上{。在大括号后面,输入ev.dataTransfer.effectAllowed ='move';然后,在新的一行上,输入ev.dataTransfer.setData("text/plain", ev.target.getAttribute('id'));以设置数据类型和目标属性。最后,输入return true;并加上一个闭合的}来完成函数。

function dragDefine(ev) {ev.dataTransfer.effectAllowed = 'move'; ev.dataTransfer.setData("text/plain", ev.target.getAttribute('id')); return true;}

现在,我们需要定义dragOver函数。输入dragOver(ev)和一个开头的{,然后通过添加ev.preventDefault()来调用preventDefault()函数。函数块应该类似于下面的代码:

function dragOver(ev) { ev.preventDefault();}

我们需要的下一个函数是指示拖动完成的函数。输入function dragEnd(ev),然后一个开头的{。输入return true; }来完成函数。

输入function dragDrop(ev)并加上一个开头的{,然后换行添加我们的第一个方法。输入var idDrag = ev.dataTransfer.getData("Text")来创建一个将保存文本字符串的拖动变量,然后输入ev.target.appendChild (document.getElementById(idDrag))。完成函数后,输入ev.preventDefault()。函数块应该如下所示代码:

function dragDrop(ev) {
var idDrag = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(idDrag));
ev.preventDefault();} </script>

关闭页面的头部部分。输入<body><header>,然后<h1>拖放井字棋</h1></header>来完成页面的标题。

</head><body><header><h1>Drag and Drop Tic Tac Toe</h1></header>

接下来,输入<section><h3>将字母从灰色框拖到游戏板上(然后再拖回去!)</h3>

创建一个 ID 为"gametilebox"的 div,并设置ondragover ="dragOver(event)"ondrop="dragDrop(event)"。它应该如下所示:

<div id="gametilebox" ondragover="dragOver(event)" ondrop="dragDrop(event)">

现在,我们将为每个游戏瓷砖创建一个div。创建六个**“X"瓷砖和六个"O”**瓷砖,每个都以从1-12的数字结尾的id开始。每个div将包含类"lettertile",每个draggable属性将包含值"true"。每个瓷砖还将包含ondragstart="return dragDefine(event)"ondragend="dragEnd(event)"div块应该看起来像以下代码:

<div id="lettertile1" class="lettertile" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">X</div>
<div id="lettertile2" class="lettertile" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">X</div>
<div id="lettertile3" class="lettertile" draggable="true" ondragstart="return dragDefine(event)" ondragend="dragEnd(event)">X</div>

现在,我们可以为我们在stylesheet.css中创建的块样式创建实际的divs。首先键入<div id= "gameboard">。应该为每个块 id 创建一个div,从"blockA"到"blockI"。它们每个都将包含一个ondragover="return dragOver(event)"和一个ondrop="dragDrop(event)"。它们应该看起来像以下代码块。

<div id="blockA" ondragover="return dragOver(event)" ondrop="dragDrop(event)"></div>
<div id="blockB" ondragover="return dragOver(event)" ondrop="dragDrop(event)"></div>
<div id="blockC" ondragover="return dragOver(event)" ondrop="dragDrop(event)"></div>

bodyhtml的闭合标签关闭页面,将文件命名为"using-drag-drop-api.html",然后在浏览器窗口中查看结果。拖动几个字母,结果应该类似于以下截图:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_02.jpg

它是如何工作的…

首先,我们创建了一个基本的 HTML5 页面,并使用@fontface添加了一个草图字体作为标题,以使我们的游戏具有有趣的视觉效果。接下来,我们通过将margin设置为body和所有块级元素的display:block来为页面设置样式,以便更好地控制这些元素的呈现。在样式化标题字体后,我们为游戏瓷砖框定义了widthheight。这将是容纳组成游戏瓷砖的字母的容器。

我们通过在 IE 浏览器中键入一个特殊的注释标签来开始我们的脚本,以指向一个额外的脚本文件来触发 HTML5 元素:<!--[if IE]><script src="img/html5.js"></script><![endif]-->。这是由 Remy Sharp(http://remysharp.com/html5-enabling-script/)根据 MIT 许可证提供的,以在处理 Internet Explorer 时保持我们的理智。

当用户开始拖动物品时,dragDefine()函数被调用。它首先检查物品是否可拖动,使用dataTransfer.effectAllowed='move'。然后,它将要传输的数据类型设置为text,并使用dataTransfer.setData("text/plain")target.getAttribute('id'))来识别目标的id。该函数返回 true,表示可以拖动对象。

接下来,我们定义了dragOver函数,当拖动的物品位于另一个物品上时调用,接受一个名为ev的事件参数,然后使用它来调用preventDefault()以允许放置物品。拖放 API 规范明确规定,我们必须取消拖动,然后准备放置。

然后创建了dragEnd()函数,当拖动完成时返回 true。它还接受一个事件参数。

完成所有拖动功能后,我们准备创建代码来放置物品。dragDrop()函数接受一个事件参数,并使用该值获取文本对象的值,然后将其传递给一个新变量var idDrag来保存文本字符串,然后再使用getElementById来识别正确的元素 ID 进行放置。就像dragEnd()一样,我们必须调用拖放 API 中的preventDefault()函数来指示可以放置对象。

在关闭页面的头部区域后,在 body 中放置了内容框来容纳我们的字母瓷砖和游戏板块。这些由两个父 div 容器组成,每个容器都包含包含字母瓷砖或游戏板网格部分的子 div。

游戏瓷砖框在拖动字母瓷砖时调用了dragOver()函数。字母瓷砖 div 本身通过draggable="true"变得可拖动,并在拖动时返回dragDefine()。当拖动停止时,它们调用dragEnd()函数。

因为我们希望字母块能够被放下并停留在游戏板的特定区域,我们为网格上的每个单独的块创建了 div,以便在它们被放到板上时保持我们的字母在那里,并在对象被拖动到它们上方时返回dragOver事件,并在对象被放到它们上时调用dragDrop()

为什么要费心设置块 div?我们本可以在左边设置我们的游戏块盒子,右边设置游戏板,然后就完成了。结果会是,当我们从左边的盒子拖动块到游戏板时,它们会被放下并按照它们被放下的顺序排列,而不是我们想要放置它们的地方。这种默认行为在你想要对列表进行排序时很好,但当需要精确控制对象放置位置时就不行了。

我们需要覆盖当对象被放下时产生的默认行为。我们创建了九个游戏板块,都是相同的基本大小。每个块的主要变化是paddingmargin

花几分钟时间阅读www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html上的拖放规范,你会注意到他们明确表示他们只定义了一个拖放机制,而不是你必须执行的操作。为什么?因为使用智能手机或其他触摸屏设备的用户可能没有鼠标等指针设备。

还有更多…

这个拖放 API 的演示可以通过多种方式构建成一个完整的游戏,包括计分、游戏板重置按钮和其他交互元素。

创建一个基于画布的井字棋游戏

可以使用两个画布,一个用于游戏块盒子,另一个用于游戏板。可以使用画布动态绘制板和游戏块,然后在屏幕上写入分数或消息,比如“你赢了”。

在用户玩游戏时显示响应消息

Remy Sharp 在html5demos.com/drag-anything上有一个很棒的演示,展示了当一个对象被放下时如何在屏幕上显示消息。

要被放下的对象的源标签类似于:

<div id="draggables"><img src="img/picean.png" alt="Fish" data-science-fact="Fish are aquatic vertebrates (animals with backbones) with fins for appendages." /> </div>

当对象被拖动到时,“放置区”框可能如下所示:

<div class="drop" id="dropnames" data-accept="science-fact"> <p>Learn a science fact!</p> </div>

当图像被放入框中时,你会看到包含在“data-science-fact”中的文本,而不是图像。

另请参见

jQuery 的 Packt 书籍,本书中的其他配方,以及高级 HTML5 的 Packt 书籍。

使用 vid.ly 和 jQuery 支持跨浏览器视频

支持大多数浏览器需要将视频编码为多种格式,然后将正确的格式提供给浏览器。在这个配方中,我们将使用一个名为 vid.ly 的在线视频显示库(www.vid.ly),在多个浏览器上可靠地准备和分享视频,并在页面上改变背景颜色。

准备工作

你需要一个视频上传到www.vid.ly。一些浏览器不允许本地提供文件,所以你可能也需要一个地方来上传你的文件和测试页面。

如何做…

输入<!DOCTYPE html> <html lang="en"> <head>,然后开始添加样式声明,输入<style type="text/css"> h2{color:#303;}

样式一个 div 来包含特色内容:#featured {position:relative; padding: 40px; width: 480px; background-color:#000000; outline: #333 solid 10px; }

输入video {padding: 3px;background-color:black;}来创建视频标签的样式,然后添加一个闭合的</style>标签。

在页面中声明使用的脚本。键入<script src="img/jquery.min.js" type="text/javascript" charset="utf-8"></script>来引用主要 jQuery 库的最小化版本。然后,键入<script type="text/javascript" src="img/jquery-ui.min.js"></script>来引用用于颜色变化效果的 jQuery UI 库。最后,我们将通过在关闭</head>标签之前键入<script type="text/javascript" src="img/mycolor.js"></script>来引用我们自己的脚本。

输入一个开放的<body><section>标签,然后键入<header> <h2>Featured Video</h2></header>来显示页面标题。

现在,我们可以创建包含我们之前样式化的特色内容的 div。键入<div id="featured"> <p>此视频已通过<a href="http://vid.ly">vid.ly</a>转换为跨浏览器格式</p>

下一步是将视频剪辑上传到vid.ly进行多文件格式转换。转换过程完成后,您将收到一封电子邮件,然后可以获取视频的代码片段,如下截图所示:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_03.jpg

复制网站上的代码,然后粘贴到您的页面中。视频和脚本标签中的src值应该是 vid.ly 给出的 URL。代码块应该如下所示:

<video id= "vidly-video" controls="controls" width="480" height="360"> <source src="img/7m5x7w?content=video"/> <script id="vidjs" language="javascript" src="img/html5.js"></script> </video>

为了增加一些额外的乐趣,让我们在页面上添加另一个视频标签。键入以下代码:<p>哎呀,这是一个宝宝视频!</p>,为视频标签使用不同的 id,并按照以下方式调整大小:<video id="tinymovie1" controls="controls" width="190" height="120">,然后使用相同的源标签:<source src="img/7m5x7w?content=video"/><script id="vidjs" language="javascript" src="img/html5.js"></script></video>,并关闭页面:</div> </section></body></html>。将文件保存为display-videos-using-videly.html

我们要做的最后一件事是创建一个 jQuery 脚本来改变#featured div 的背景颜色。打开您的编辑器,创建一个名为myColor.js的新文件。

键入$(document).ready(function() {,然后转到新的一行,键入调用动画函数并改变背景颜色的代码:$('#featured').animate({'backgroundColor':'#ff3333', 'color': '#ffffff'}, 6000);});。

在浏览器中加载页面,观察主视频加载时颜色的变化。您可以看到以下截图显示的效果:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_04.jpg

工作原理…

首先,我们创建了一个标准的 HTML5 页面,并开始添加样式声明。我们将featured div 的位置设置为相对位置,以便在将来如果决定添加额外的 jQuery 效果时具有更大的灵活性。通过将padding设置为40px,将outline颜色设置为深灰色并加粗为10px,创建了强烈的视觉效果。默认的背景颜色设置为黑色(#000000),以便与最终的红色背景进行高对比度的比较。

接下来,我们样式化了video标签,使其在加载时具有黑色的background-color。我们还可以在这里添加一个背景图像作为海报。

接下来,使用<script src="img/jquery.min.js" type="text/javascript" charset="utf-8"></script>声明了基本的 jQuery 脚本。因为它不包含animate()等效果,我们还需要引用用于颜色变化效果的 jQuery UI 库的最小化版本。然后,通过键入<script type="text/javascript" src="img/mycolor.js"></script>来添加对我们自己脚本的引用。进一步减小脚本文件大小的另一种方法是创建一个仅包含来自 jQueryUI 库的动画效果的自定义脚本。

接下来,我们创建了主页面内容,包括指向 vid.ly 上的视频的链接。vid.ly 提供的默认代码会将 ID'vidley video'应用到video标签,但如果您想使用自己的样式 ID 或将为每个视频使用不同的 ID,则可以省略该代码。另一个选择是将所有视频分配相同的类,然后根据需要为它们分配唯一的 ID。

另请参阅

第八章,拥抱音频和视频,更详细地介绍了视频元素。

使用 jQuery 动态显示视频

视频元素使我们能够像处理图像一样处理视频,并以有趣和令人兴奋的方式操纵它们。

准备工作

您需要一个以多种文件格式提供的视频(这些文件在本书的章节代码中提供)。建议上传文件的服务器,因为并非所有浏览器都以可预测的方式本地播放文件。

操作步骤

首先,我们必须准备一个 HTML5 页面来放置它。输入我们页面的开放标签:<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Video Explosion</title>

打开下载的代码文件中的stylesheet.css文件,或创建一个同名的新文件。

输入以下内容来设置 body 样式:body {background: white;color:#333333; },然后按照以下方式设置 div 标签的样式:div {float:left; border:1px solid #444444;padding:5px;margin:5px; background:#999999;}

我们需要创建和设置的第一个独特的 div 是#featured。输入#featured {position:relative; width: 480px; background-color:#f2f1f1;}来创建样式。

现在创建一个名为details的 div 来容纳一个小的信息框。输入#details{ position:relative;display:block;background-color:#6CF;color:#333333; padding:10px;}以创建一个将显示在featured div 旁边的 div。

保存css文件,并在 html 页面的头部引用它,方法是使用链接标签输入<link rel="stylesheet" href="css/stylesheet.css"type="text/css" media="screen" charset="utf-8"/>

在样式表链接下方输入以下链接到主 jQuery 库:<script src="img/jquery-latest.js" type="text/javascript" charset="utf-8"></script>,然后通过输入<script type="text/javascript" src="img/jquery-ui.min.js"></script>来链接到 jQuery UI 库。最后,通过输入<script type="text/javascript" src="img/explode.js"></script>来添加对即将创建的脚本的引用。

创建一个新文件并命名为explode.js,并将其存储在一个名为js的新子文件夹中。输入$(document).ready(function(){}。在两个大括号({})之间输入$('h1').effect('shake', {times:5}, 200);创建将导致 featured div 标签中包含的内容爆炸的语句。在新行上,输入$('#featured').effect('shake', {times:3}, 100).delay(500).hide('explode',{}, 2000).slideDown('fast'););以完成脚本。您的代码块应该类似于以下代码块:

$(document).ready(function(){ $('h1').effect('shake', {times:5}, 200); $('#featured').delay(2000).hide('explode', {}, 2000 ).slideDown('fast'); });

保存文件并返回 html 页面。

为 HTML 文件添加</head>闭合标签和<body>开放标签。接下来,输入一个开放的<header>标签和标题文本:<h1>Featured Moto Video</h1>,然后输入</header>标签来完成标题区域。

创建一个开放的<section>标签,然后输入<div id="featured">来创建一个 div,用于容纳我们的视频标签和相关元素。输入<video id="movie" width="480" height="360" preload controls>,然后为三种视频文件类型的每一个添加一个 source 标签:<source src='motogoggles.ogv' type='video/ogg; codecs="theora, vorbis"'/> <source src='motogoggles.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'/> <source src='motogoggles.webm' type='video/webm; codecs="vp8, vorbis"'/>,然后使用</video>标签和</div>标签来关闭 featured div。

最终的内容块包含在details div 中。要创建它,输入<div id="details">,然后添加一个带有文本的标题标签<h1>Details</h1>,最后是一个简短的解释性文本段落:<p>视频将爆炸然后再次出现!</p>。关闭</div></section> </body></html>标签。将 HTML 文件保存为exploding-video-dynamically.html,在浏览器中打开它以查看结果。它们应该与以下截图类似,显示视频分成几部分并爆炸。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_05.jpg

它是如何工作的…

stylesheet.css文件包含了特色 div 的样式,确定了页面上视频对象的位置。要注意的第一件重要的事情是position设置为relative。这使我们能够移动视频对象并使用 jQuery 执行其他操作。

我们创建了一个名为details的 div,其position也是relative,但background-color设置为浅蓝色(#6CF)。不同的颜色将有助于在视觉上将其与视频对象区分开来。

接下来,我们添加了 jQuery 库脚本。为了让我们能够访问animate类中包含的方法和函数,需要引用 jQuery UI 库。在这个例子中,我们是在本地引用它,但您也可以像我们访问主要的 jQuery 库一样链接到它。

最后,我们能够编写自己的脚本,使页面上的元素摇晃和爆炸!我们创建了一个语句来验证页面是否准备好接受我们的代码,方法是键入$(document).ready(function(){}。这个函数查询 DOM 并询问页面是否已加载并准备好接受脚本。在创建 jQuery 脚本时,使用这个包装函数是最佳实践。我们使用别名符号$来调用 jQuery 函数,以抓取h1选择器,并对其应用包含shake参数的effect动作,使元素向侧面移动,其中又包含了一个关于摇动元素的次数的参数。摇动应持续的时间间隔以毫秒定义,本例中为200。我们使用选择器$('#featured')来抓取特色 div 元素,并像对h1标签所做的那样,对其进行摇动(只摇动三次以增加变化),每次摇动持续100毫秒。现在我们添加了一些新的动作。在shakes和爆炸之间添加了500毫秒的delay,并使用.delay(500)命令附加到该命令。然后我们附加了hide动作,参数为explode,默认情况下将发生一次,持续时间为2000毫秒。视频爆炸后,slidedown动作将其以fast参数滑回屏幕上。请注意,爆炸所用的时间有点长,这样我们可以更容易地看到它。100-500毫秒的时间间隔会产生更真实的爆炸效果。如果您只想要视频本身而不是特色标签提供的背景或边框,也可以直接使用$('video')来抓取视频标签。

回到 HTML 文件,我们将视频放在一个名为featured的容器 div 中,并创建了一个父video标签,它将preload并包含默认的controls。在关闭video标签之前,我们在其中嵌套了三种视频文件类型的source标签,以便不同浏览器的用户都可以观看视频:我们没有提供 FLASH 回退,但我们可以使用 JavaScript 库,比如Video.js。然后我们关闭了</video>标签和特色 div 标签</div>

最后,我们创建了一个 div 来保存关于用户可以期待在details div 中发生的事情的信息。

还有更多…

视频元素、JavaScript 和画布标签还有很多可以做的事情。继续阅读更多实验。

使用视频和画布进行更多交互式爆炸

Sean Christmann 在www.craftymind.com上进行了一项令人惊叹的实验,使您能够在视频播放时实时爆炸多个视频部分。您可以在此处查看:www.craftymind.com/2010/04/20/blowing-up-html5-video-and-mapping-it-into-3d-space/,但请注意 - 在 Firefox 中资源消耗非常大。

所有这些爆炸是怎么回事?

起初似乎没有任何真正实际的理由来分解视频。然而,这对于模仿独特的过渡效果或对游戏中用户操作的响应可能非常有用。

实时 Chroma 键背景替换

Firefox 开发人员一直在尝试操纵视频元素。他们创建了一个教程,解释了他们如何使用画布、JavaScript 和视频元素的属性执行 Chroma 键替换。您可以在以下网址阅读有关此内容并查看演示:developer.mozilla.org/En/Manipulating_video_using_canvas

想象一下在网站上显示视频,您可以显示异国情调的背景或创建产品和人物的互动混搭。

另请参阅

视频元素在本书的第八章拥抱音频和视频中进行了深入探讨。

使用 jQuery 创建可移动视频广告

我们将在网站上创建一个视频广告,当用户向下滚动页面时,它将移动使用 jQuery 和视频标签。

准备工作

您将需要多种格式的视频文件,如.ogg/.ogv, .mp4.webm,或者使用视频服务,如www.vid.ly.com来提供跨浏览器视频。此示例未在 Internet Explorer 中进行测试,但应在 Safari、Google Chrome、Opera 和 Firefox 的最新版本中正常工作。

如何做…

我们将首先创建一个典型的网页。在编辑器中打开一个新文件,并将其保存为movable-video-ad.html。键入<!DOCTYPE html> <html lang="en"><head><meta charset="utf-8" /><title>Movable Video Ad</title>以在页面上放置第一个标签。

现在,为我们的默认样式表创建一个引用链接<link rel="stylesheet" href="css/main.css" type="text/css" media="screen" charset="utf-8" />和一个名为<link rel="stylesheet" href="css/scroll.css" type="text/css" media="screen" charset="utf-8" />的辅助样式表。

接下来,为 jQuery 脚本创建引用链接。键入<script src="img/jquery-1.4.min.js" type="text/javascript" charset="utf-8"></script>来引用核心 jQuery 代码。添加链接语句<script type="text/javascript" src="img/jquery-ui-1.7.2.custom.min.js"></script>。我们将链接到的最终脚本是我们为名为myAd.js的配方创建的自己的脚本,它将存储在我们创建的名为"js"的子文件夹中。键入<script type="text/javascript" src="img/myAd.js"></script>来链接到该文件。

键入</head><body><div id="container">开始页面的内容区域。通过键入<header> <h1>Motocross Mania</h1></header>来显示页面标题。

通过键入<div id="content"> <h2>No dirt = no fun</h2>来开始添加页面内容。现在可以通过输入文本<div id="motoad"><h3>Buy this movie!</h3>,然后在段落元素标签中包含电影标题<p><strong>MotoHelmet</strong></p>来向页面添加包含广告的 div。

然后应添加一个视频标签<video width="190" height="143" preload controls>。键入包含每种视频格式的源标签,如下面的代码块所示:

<source src='video/motohelmet.ogv' type='video/ogg; codecs="theora, vorbis"'/> <source src='video/motohelmet.mp4' type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'/> <source src='video/motohelmet.webm' type='video/webm; codecs="vp8, vorbis"'/></video>

关闭</div>标签并保存到目前为止的进度。

创建一个带有 id 为 intro 的段落<p id="intro">来包含文本We review the best motorcross gear ever!!!。在段落标签和文本后面,加上一个虚拟链接列表:<ul><li><a href="#">Helmets</a></li> <li><a href="#">Gloves</a></li><li><a href="#">Goggles</a></li></ul>,用</p>关闭段落,然后创建一个新的 div 来包含一个虚拟新闻内容块,然后是另外两个虚拟 div 块,一个页脚标签,以及关闭页面元素,如下面的代码块所示:

<div id="news"><h2>Latest News</h2> <p>Trip Ousplat admits he doesn't do his own stunts! "My mom makes
me use a stunt double sometimes," The shy trick-riding sensation explains.</p> <p>Gloria Camshaft smokes the competition for a suprise win at the Hidden Beverage Playoffs</p> <p>Supercross competitors report more injuries; jumps more extreme than ever</p><p>James Steward still polite, reporters bored</p>
</div><div id="filler"><h2>On Location</h2> <p>Grass is not greener as there is no grass on most motorcross trails experts claim </p></div> <p id="disclaimer">Disclaimer! Anything you choose to do is at your own risk. Got it? Good.</p><footer><p>&copy; Copyright 2011 Motocross Extreme Publications, Inc.</p></footer></div></body></html>

现在,我们将在main.css文件中为页面元素设置样式。第一个关键样式是#container div。它应该有一个0 auto的边距和650px的宽度。接下来,#motoad div 应该被设置为右浮动,并包含一个200px的宽度来容纳视频元素。最后,#intro div 应该包含一个较短的450px宽度。这三个样式应该看起来类似于下面显示的代码块:

#container{ margin:0 auto;text-align:left; width: 650px;}
#motoad{ float:right;width:200px;}
#intro{width:450px;}

其余的样式是对填充和颜色或其他标准声明的微小调整。

现在,打开scroll.css文件来定义样式,以帮助我们的广告滚动。我们将级联#motoad的属性,形成一个可以移动的 div 块。接下来,定义#content属性的height,以及段落和h2元素的宽度。scroll.css中的样式现在应该如下所示:

#motoad {display:block;position: relative; background-color:#FC0;width:200px;padding:10px;}
#content { height:1000px;}
p {width:450px;}h2 {width:460px;}

保存文件,并准备创建我们的 jQuery 脚本。

打开或创建myAd.js,并开始输入文档就绪函数$(document).ready(function(){}和花括号。在花括号之间点击 enter,并输入滚动函数$(window).scroll(function() {。在该函数的开头花括号后键入命令:$('#motoad').stop().animate({top: $(document).scrollTop()},'slow','easeOutBack');。也要关闭脚本:" });});"。我们的 jQuery 脚本现在应该看起来像以下代码块:

$(document).ready(function(){ $(window).scroll(function() { $('#motoad').stop().animate({top: $(document).scrollTop()},'slow','easeOutBack'); }); });

保存所有文件,并在浏览器窗口中加载 HTML 页面。在开始滚动页面之前,页面应该看起来像下面的截图。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_06.jpg

尝试向上和向下滚动页面。广告也应该随着页面一起上下移动。结果应该看起来类似于以下截图:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_07.jpg

工作原理…

在创建了一个包含不同内容元素的典型 HTML 页面后,我们准备好为 CSS 页面设置样式。我们将 CSS 分成两个文件,main.cssscroll.css,这样当我们在 jQuery 脚本中调用滚动函数并积极应用它时,页面上的内容元素会收缩,以便我们的广告可以轻松移动,而不会阻挡页面上的任何信息。

我们希望在调用窗口滚动事件时,使#motoad div 标签移动。为此,我们使用别名符号$来调用 jQuery 函数,从 DOM 中获取window选择器,并将默认滚动动作参数应用于它。使用这个函数,我们然后创建了控制#motoad div 块行为的命令。我们给它了stop的动作,这样它就准备好进行动画。animate动作链接到了stop命令。我们应用到#motoad div 的animate的第一个参数是,当文档窗口中的滚动条移动时,div 会移动。slow参数控制了广告上下移动的速度,easeOutBack参数引用了一个缓动命令,以创建流畅的动画运动,而不是突然开始或停止。

还有更多…

在这个示例中,我们通过使自定义 HTML 元素对页面上的用户操作做出响应来实现了动画效果。这只是我们可以微妙地添加效果的一种方式,可以用于实际解决方案。

有 HTML 元素,就会移动

探索 jQuery UI 库,你会被许多可以操纵和样式化任何 HTML 元素的方式所启发。访问jqueryui.com查看演示和文档。

另请参阅

学习 jQuery:使用简单的 JavaScript 技术实现更好的交互设计和 Web 开发,Packt Publishing 出版。

使用 Easel.js 和 canvas 标签控制图像的显示

JavaScript 库Easel.js减少了使用canvas标签创建动画和丰富交互环境的复杂性。在这个配方中,我们将使用单个文件中名为"sprites"的一系列图像,以展示如何使用Easel.js来控制精灵中选择性显示的图形图像。

准备工作

您需要下载Easel.js库,或者使用此配方的代码文件中的副本。

如何做…

创建一个 HTML5 文件的开放标签。您的代码应该类似于以下代码块:

<!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title> Animating images using BitmapSequence and SpriteSheet</title>

接下来,链接到此配方中使用的主样式表styles.css:。

接下来,我们将通过插入以下脚本文件的链接来导入Easel.js框架库:UID.js, SpriteSheetUtils.js, SpriteSheet.js, DisplayObject.js, Container.js, Stage.js, BitmapSequence.jsTicks.js。您可以在这里看到每个脚本文件的路径和链接:

<script src="img/UID.js"></script><script src="img/SpriteSheetUtils.js"></script><script src="img/SpriteSheet.js"></script><script src="img/DisplayObject.js"></script><script src="img/Container.js"></script><script src="img/Stage.js"></script><script src="img/BitmapSequence.js"></script><script src="img/Tick.js"></script>

接下来,创建并打开<script>标签,并声明以下三个变量:var canvas; var stage; var critterSheet = new Image(); 用于我们的脚本。

输入function init(){开始函数,然后输入canvas = document.getElementById("testCanvas");将页面主体中的 canvas 与 canvas 变量绑定。准备加载一个新的spriteSheet,输入critterSheet.onload = handleImageLoad;。critterSheet变量存储精灵图像的来源。输入critterSheet.src = "images/moles.png";来加载我们自己的一系列鼹鼠图像。函数块应如下代码块所示:

function init() {
canvas = document.getElementById("testCanvas");
critterSheet.onload = handleImageLoad;
critterSheet.src = "images/moles.png";}

我们将创建的第二个函数是handleImageLoad()。输入function handleImageLoad() {然后输入stage = new Stage(canvas);来创建一个新的舞台实例。输入var spriteSheet = new SpriteSheet(critterSheet, 76, 80);来创建一个新的spriteSheet。创建一个名为critter1的新位图序列变量,并定义它在舞台上的位置,使用 x 和 y 坐标来输入:var critter1 = new BitmapSequence(spriteSheet); critter1.y = 85; critter1.x = 85;。通过输入critter1.gotoAndStop(1),从我们的精灵表moles.png中添加一个小动物。接下来,使用命令stage.addChild(critter1)将其添加到舞台上。

克隆我们创建的第一个critter1变量,并通过输入var critter2 = critter1.clone()将其值传递给一个新的 critter 变量。通过添加到其当前位置值来将新变量定位在第一个 critter 的右侧,使用critter2.x += 120

输入critter2.gotoAndStop(0)来为critter2变量赋值。克隆 critter 1 和 critter 2 的代码块应如下所示:

var critter2 = critter1.clone();
critter2.x += 120;
critter2.gotoAndStop(0);
stage.addChild(critter2);

Tick 间隔Tick.setInterval(300);和监听器Tick.addListener(stage);是我们将添加到脚本的最后两个语句。关闭handleImageLoad()函数的大括号(}),然后输入一个闭合的脚本标签。

关闭</head>标签,然后输入带有onload属性的开放body标签,调用init()函数。创建一个名为"description"的 div 用于内容。添加一个名为canvasHolder的 div 来包含 canvas 元素。在页面底部显示图像文件moles.png

<body onload="init();">
<div class="description">Using <strong>BitmapSequence</strong> to animate images from a <strong>SpriteSheet</strong>.
</div>
<div class="canvasHolder">
<canvas id="testCanvas" width="980" height="280" style="background-color:#096"></canvas> </div> </p><p>The original moles.png spritesheet file with all the images:<br/><img src="img/moles.png"/></p> </body></html>

将文件保存为whack-mole-easel-test-single.html。结果可以在以下截图中看到:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_08.jpg

工作原理…

在我们设置好 HTML5 页面的开头之后,我们准备好导入Easel.js框架并创建我们的主要脚本。

我们创建了一个开放的<script>标签,并声明了以下全局变量:var canvas; var stage; var critterSheet = new Image(); 用于我们的脚本。

创建的init()函数将在页面加载时被调用。它包含了正在被分配选择器testCanvascanvas变量的过程,使用document.getElementById("testCanvas");将页面主体中的 canvas 与 canvas 变量绑定。接下来,我们准备通过输入critterSheet.onload = handleImageLoad加载一个新的spriteSheetcritterSheet变量存储了精灵图像的来源。输入critterSheet.src = "images/moles.png";让我们可以访问我们自己的一系列鼹鼠图像。

我们创建的第二个函数是handleImageLoad()。在这个函数中,我们做了大部分工作,首先是使用stage = new Stage(canvas)创建了一个舞台的新实例;接下来,我们使用var spriteSheet = new SpriteSheet(critterSheet, 76, 80)创建了一个新的spriteSheet

现在我们有了一个精灵图实例,我们可以创建一个新的位图序列变量,称为critter1,并定义它在舞台上的位置,使用 x 和 y 坐标来输入:var critter1 = new BitmapSequence(spriteSheet);critter1.y = 85;critter1.x = 85;。接下来,我们按数字引用要添加的帧,以便首先将正确的动作应用于 critter,然后应用于舞台。我们通过输入critter1.gotoAndStop(1)critter1变量链接到我们精灵图moles.png上的第二个图像。我们使用命令stage.addChild(critter1)将图像添加到舞台上。

我们克隆了我们创建的第一个critter1变量,并通过输入var critter2 = critter1.clone()将其值传递给一个新的 critter 变量。我们通过使用critter2.x += 120将新变量定位在第一个 critter 的右侧,将其当前位置值添加到其中。我们通过命令BitSequence去到moles.png上的第一个图像的位置并在那里停止,并将其分配给critter2变量。

我们添加了Tick.setInterval(300);,这样就在Ticks之间应用了300毫秒的时间间隔。Tick 接口充当全局定时设备,如果需要,可以返回每秒帧数(FPS)。我们向舞台添加了一个监听器Tick.addListener(stage);,它的行为类似于其他类型的监听器,它监听Ticks。这可以用来在指定的时间重新绘制舞台,或执行其他与时间相关的操作。

我们使用onload属性在body标签中调用init()函数。这会导致在页面加载时调用init()函数。

另请参阅

动画序列教程。

使用 Easel.js 和 canvas 标签来制作图像序列的动画

我们可以通过创建数组和使用Easel.js JavaScript 库的函数来制作称为精灵的图像条,然后使用canvas元素对它们进行操作。在这个教程中,我们将对同一条图像条进行动画处理,但显示两个不同时间序列。

准备工作

下载此教程的代码文件,以使用Easel.js框架库以及支持文件。您需要一个能够正确显示 HTML5 元素并测试本教程中使用的代码的最新浏览器。

操作步骤

创建一个 HTML5 文件的开头标签。您的代码应该类似于以下代码块:

<!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title> Animating images using BitmapSequence and SpriteSheet</title>

链接到本教程中使用的主样式表styles.css:。

通过插入以下脚本文件的链接来导入Easel.js框架库:UID.js, SpriteSheetUtils.js, SpriteSheet.js, DisplayObject.js, Container.js, Stage.js, BitmapSequence.jsTicks.js。参考前面的示例,了解框架块应该是什么样子的。

创建一个开头的<script>标签,并声明以下三个变量:var canvas;var stage;var critterSheet = new Image();用于我们的脚本。

输入function init(){开始函数,然后输入canvas = document.getElementById("testCanvas")

准备通过输入critterSheet.onload = handleImageLoad;来加载一个新的spriteSheet。输入critterSheet.src = "images/moles.png";来加载我们自己的一系列鼹鼠图像。函数块应该如下所示的代码块:

function init() {
canvas = document.getElementById("testCanvas");
critterSheet.onload = handleImageLoad;
critterSheet.src = "images/moles.png";}

我们将创建的第二个函数是handleImageLoad()。输入function handleImageLoad() {然后stage = new Stage(canvas);创建舞台的新实例。输入var spriteSheet = new SpriteSheet(critterSheet, 80, 80);创建一个新的spriteSheet。现在我们有了一个精灵表,创建一个新的位图序列变量名为critter1,并使用 x 和 y 坐标定义其在舞台上的位置,输入:var critter1 = new BitmapSequence(spriteSheet);然后critter1.y = 100;critter1.x = 90;。接下来,我们将创建一个数组,将其映射到原始spritesheet文件上的每个图像,输入var frameData = {shymole:0, upmole:1, downmole:2, whacked:3, whackedow:4, clouds:5,tinycloud:6, cloudgroup:7};以便我们有八个名称值,每个名称值都与一个数组 ID 相关联。

到目前为止,handleImageLoad()的代码块应该如下所示:

function handleImageLoad() {
stage = new Stage(canvas);
var spriteSheet = new SpriteSheet(critterSheet, 80, 80);
var critter1 = new BitmapSequence(spriteSheet);
critter1.y = 100;
critter1.x = 90;
var frameData = {shymole:0, upmole:1, downmole:2, whacked:3, whackedow:4, clouds:5,tinycloud:6, cloudgroup:7};

通过输入:spriteSheet = new SpriteSheet(critterSheet, 80, 80, frameData);创建一个新的spriteSheet并将其用作参数。

创建一个名为critter1的新位图序列变量,并通过输入critter1gotoAndStop(0);应用图像精灵。使用stage.addchild(critter1);将critter1添加到stage

通过输入var critter2 = critter1.clone();克隆第一个critter1变量,并将其值传递给一个新的小动物变量。使用critter2.x += 120;定义新变量的x值。通过输入critter2.gotoAndStop(5);为小动物分配其自己的图像,来自moles.png图像文件。添加一个新的spriteSheet,创建critter 1和克隆critter 2的代码块应该如下所示的代码块:

spriteSheet = new SpriteSheet(critterSheet, 80, 80, frameData);
critter1.gotoAndStop(0);
stage.addChild(critter1);
var critter2 = critter1.clone();
critter2.x += 120;critter2.gotoAndStop(5);

输入:var critter3 = critter2.clone(); critter3.spriteSheet = spriteSheet;。就像我们之前创建的其他小动物变量一样,通过将10添加到其当前值来重新定义critter3x值:critter3.x += 10;。以下代码块显示了我们到目前为止所做的事情:

var critter3 = critter2.clone();
critter3.spriteSheet = spriteSheet;
critter3.x += 10;

通过输入critter3.gotoAndStop("upmole");按名称引用moles.png中的图像frames。通过克隆一个新变量并引用一个新帧,将当前的upmole帧图像替换为不同的帧:var critter4 = critter3.clone(); critter4.gotoAndStop("downmole");。通过输入critter4.x += 10;将该帧向右移动10像素。

再次交换帧并将我们的新帧向右移动10像素:var critter5 = critter4.clone(); critter5.gotoAndStop("shymole"); critter5.x += 10;。让我们看一下到目前为止我们应该有的代码块:

critter3.gotoAndStop("upmole");
var critter4 = critter3.clone();
critter4.gotoAndStop("downmole");
critter4.x += 10;
var critter5 = critter4.clone();
critter5.gotoAndStop("shymole");
critter5.x += 10;

通过输入以下内容循环播放我们的moles.png文件中的帧:

var critter6 = critter1.clone(); critter6.x = critter5.x + 100; critter6.gotoAndPlay(3);stage.addChild(critter6);.

在舞台上添加第二个动画序列,通过引用不同的起始帧来改变动画的时序,当新的小动物精灵被添加到舞台上时:var critter7 = critter1.clone(); critter7.x = critter6.x + 100; critter7.gotoAndPlay(1); stage.addChild(critter7);。

我们的两个动画序列现在应该包含以下代码:

var critter6 = critter1.clone();
critter6.x = critter5.x + 100;
critter6.gotoAndPlay(3);
stage.addChild(critter6);
var critter7 = critter1.clone();
critter7.x = critter6.x + 100;
critter7.gotoAndPlay(1);
stage.addChild(critter7);

Tick 间隔Tick.setInterval(200);和监听器Tick.addListener(stage);是我们将添加到脚本中的最后两个语句。关闭handleImageLoad()函数的大括号(})并输入一个闭合的脚本标签。

输入</head>,然后<body onload="init()">。创建一个名为"description"的 div 来容纳内容。最后一个 div 是canvasHolder,包含 canvas 元素。将宽度设置为600,高度设置为280,背景颜色设置为浅灰色(#ccc)。添加指向图像文件moles.png的链接,以便用户可以看到moles.png中引用的图像精灵。

保存文件,并在浏览器窗口中打开它。你应该在左侧看到一个静止的帧(闭着眼睛的鼹鼠头像),并在屏幕右侧看到两个动画序列循环播放。以下截图显示了两个序列如何加载相同的帧,但时间不同。

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_09.jpg

它是如何工作的…

创建 HTML 页面和引用画布的配方的第一步与上一个配方相同。

创建spriteSheet后,我们创建了一个新变量来保存我们的精灵帧,称为critter1,并通过输入以下内容定义了帧位置的xy坐标:var critter1 = new BitmapSequence(spriteSheet); critter1.y = 100;critter1.x = 90;。

我们创建了数组var frameData来声明八个键/值对。然后,我们能够创建一个新的spriteSheet,它接受了spriteSheet名称的参数,每个帧的默认高度和宽度,并使用frameData一次性加载moles.png中的所有帧到spriteSheet中。

接下来,我们尝试使用frameData通过数字值和名称键引用帧,创建一系列位图序列,然后用它们的克隆替换它们。

我们对序列进行了动画处理,并将它们放在了舞台上。它们都遵循相同的格式,但通过更改gotoAndPlay操作中的数字参数,它们在不同的帧上开始它们的动画序列。

最后,我们添加了Tick.setInterval(200);,它在 Ticks 之间应用了 200 毫秒的时间间隔。Tick 接口充当全局定时设备,如果需要,可以返回每秒帧数(FPS)。我们向舞台添加了一个监听器Tick.addListener(stage);,它像其他类型的监听器一样监听 Ticks。这可以用来在指定时间重新绘制舞台,或执行其他与时间相关的操作。我们使用onload属性在body标签中调用init()函数。这会导致在页面加载时调用init()函数。

还有更多…

Easel.js和其他类似的库使控制 HTML5 元素变得更加容易。不过要小心使用它们,因为有些可能不够稳定,不能在生产环境中使用。

海盗爱雏菊,你也应该爱

Easel.js的创建者被微软要求创建一个名为 Pirates love daisies 的概念性网络游戏(www.pirateslovedaisies.com),完全使用 HTML5 和 JavaScript,并且严重依赖于Easel.js库来操作canvas元素。你可以在任何网络浏览器中玩这个游戏,也许有些讽刺的是,它还为使用 Internet Explorer 9 浏览器的访问者提供了特殊功能。

老派计算机动画技术的回归

当我第一次开始在计算机上玩游戏时,游戏屏幕上有 256 种颜色和 8 位动画是一件大事。计算机动画师使用了许多技巧来复制水流动等效果。重新体验那些日子(或者第一次通过 effect games 的演示发现它们:www.effectgames.com/demos/canvascycle/

另请参阅

本书中有一整章关于 canvas 的配方。如果你跳过了它们,现在就去吞食它们。

使用 canvas 标签和 JavaScript 进行随机动画和音频

在这个配方中,我们将使用 canvas 标签来绘制和动画一系列形状。我们还将使用音频标签循环播放音频文件,同时显示动画。我们正在改编 Michael Nutt 创建的原始动画。我们将创建一个更慢、更轻松的动画,看起来像是摇曳的草。

做好准备

您将需要一个最近更新的浏览器,如 Firefox 3.6 或 Google Chrome,以及多种格式的音频文件。在 Opera 浏览器 9 和 10 中,它显示的大小会有所不同(更小)。在那些版本的 Opera 中,音频也不会播放。

如何做…

首先,打开一个新的 HTML5 页面,并命名为random-animation-with-audio.html。输入一个 HTML5 页面的开头,包括页面标题:

<!DOCTYPE html> <html lang="en"> <head><meta charset="utf-8" /> <title>Canvas Reggae</title>.

然后,添加链接到 JavaScript 和 CSS 文件,这些文件将在页面加载时导入:<script type="text/javascript" src="img/animatedlines.js"></script><link rel="stylesheet" href="css/stylesheet.css" type="text/css" media="screen" charset="utf-8" />,并使用</head>关闭 head 标签。

输入<body onLoad="init();">来在页面加载时激活init()函数。

接下来,我们创建页面的标题<header><h1>CANVAS Reggae</h1></header>,然后通过输入<canvas id="tutorial" width="480" height="360"></canvas>来添加 canvas 元素。

创建一个新的 div,其中包含一个id为 credits 的链接到 Michael 的网站:<div id="credits">Based on Canvas Party by <a href="http://nuttnet.net/">Michael Nutt</a>&nbsp;&nbsp;。然后向 div 添加一个链接,以抓取音频元素并在单击链接时应用pause()函数来暂停音乐。<a href="#" onClick="document.getElementsByTagName('audio')[0].pause();">[OFF]</a></div>

现在,输入音频标签,并将 autoplay 设置为 true,loop 设置为 loop:<audio autoplay="true" loop="loop">创建两个 source 标签来包含音频格式:<source type="audio/ogg" src="img/randomreggae.ogg" /><source type="audio/mpeg" src="img/randomreggae.mp3" />

在关闭音频标签之前,我们将添加一串文本,如果不支持音频标签,则会显示:Your browser doesn't recognize the HTML5 audio tag

关闭音频、body 和 html 标签,并保存页面。

在创建脚本之前,打开stylesheet.css页面,并输入以下内容:

body { margin: 0; background-color: #000; color: #FFF; font-family: Helvetica, sans-serif; }
a { color: #FFF; }
h1 { position: absolute; top: 0; margin: auto; z-index: 50; padding: 10px; background-color: #000; color: #FFF; }
div#credits { position: absolute; bottom: 0; right: 0; padding: 10px; }
audio { position: absolute; visibility: hidden; }

现在 HTML 和 CSS 页面已经构建完成,我们将着手处理动画脚本。创建一个新的 JavaScript 文件并命名为animatedLines.js。我们将把它放在一个名为js的新子文件夹中。

首先,我们将声明 flatten 变量并创建一个新的数组函数:var flatten = function(array) { var r = []。接下来,在函数内部,我们将创建一个for语句来声明一个以一个对象开始的数组(var i = 0),然后在数组长度大于i的情况下增加数组的大小。for(var i = 0; i < array.length; i++) {。使用push函数,我们将通过输入以下内容向数组添加新值:r.push.apply(r, array[i]);},最后通过返回数组来结束函数:return r; }

到目前为止,我们的脚本应该看起来像以下代码块:

var flatten = function(array) { var r = [];
for(var i = 0; i < array.length; i++) {
r.push.apply(r, array[i]); }
return r; }

接下来,我们将创建一个名为 shuffle 的函数,它接受一个数组作为参数。输入function shuffle(array) { var tmp, current, top = array.length。在函数内部,我们有一个 if/while 循环来遍历数组中的值。通过输入以下内容将其添加到脚本中:var tmp, current, top = array.length; if(top) while(--top) { current = Math.floor(Math.random() * (top + 1)); tmp = array[current]; array[current] = array[top]; array[top] = tmp; }。在函数末尾返回数组的值。我们的随机洗牌数组值的函数现在应该看起来像以下代码块:

function shuffle(array) {
var tmp, current, top = array.length;
if(top) while(--top) {
current = Math.floor(Math.random() * (top + 1));
tmp = array[current];
array[current] = array[top];
array[top] = tmp; }
return array; }

现在,我们准备创建一个全局的canvas变量和一个context变量,输入:var canvas;和var ctx;

有了这些变量,我们可以向脚本添加init()函数,所有的动作都从这里开始。输入function init() {,然后输入语句将我们的 canvas 变量与 canvas 元素关联起来:canvas = document.getElementById('tutorial')

现在,我们将创建一个if语句来设置我们的画布变量的宽度和高度属性:if (canvas.getContext) {canvas.width = window.innerWidth; canvas.height = window.innerHeight - 100; ctx = canvas.getContext('2d'); ctx.lineJoin = "round"; setInterval("draw()", 300); }。这完成了init()函数。

接下来,我们为浏览器窗口添加一个监听器,以便在调整大小时检测:window.addEventListener('resize', function() {canvas.width = window.innerWidth;canvas.height = window.innerHeight - 100; });}

我们脚本的最新添加现在应该是:

function init() {
canvas = document.getElementById('tutorial');
if (canvas.getContext) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight - 100;
ctx = canvas.getContext('2d');
ctx.lineJoin = "round";
setInterval("draw()", 300); }
window.addEventListener('resize', function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight - 100; }); }

我们终于准备好创建一个函数来在画布上绘制形状。这个函数将包含大部分驱动形状动画的脚本。输入function draw(){ctx.globalCompositeOperation = "darker"; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height);ctx.globalCompositeOperation = "lighter";来设置画布背景的外观。

现在,我们将输入动画中要使用的颜色。我们将创建一个包含rgba值的数组的数组。类型:var colors = ["rgba(134, 154, 67, 0.8)", "rgba(196, 187, 72, 0.8)", "rgba(247, 210, 82, 1)", "rgba(225, 124, 20, 0.8)"];。我们颜色已经定义好了,现在我们将使用一个包含宽度和高度值的单独数组的数组来设置形状的宽度和高度:var data = [ [ [5, 20], [15, 2] ], [ [50, 12], [10, 14], [3, 21] ], [ [60, 8]], [ [30, 24], [15, 4], [10, 17] ], [ [5, 10] ], [ [60, 5], [10, 6], [3, 26] ], [ [20, 18] ], [ [90, 11], [40, 13], [15, 10] ], [ [70, 19] ], ]

现在,我们可以通过使用data = shuffle(data)来改变它们的宽度和高度来使形状动画化。

为了使形状上下以及左右移动,我们需要"压扁"或压缩它们的高度。创建一个新变量来包含var flatData = flatten(data)

现在,我们将扭曲线条,使它们看起来像是在不同方向上拉动并使用bezierCurve。这是一个大的函数块,包含在我们之前创建的draw()函数中,所以输入link()函数如下所示:

link(topPos, bottomPos, width) {
var padding = 100;
ctx.lineWidth = width;
ctx.beginPath();
var height = parseInt(canvas.height - padding);
var pull = 100;
var topLeft = topPos + (width / 2) + padding;
var bottomLeft = bottomPos + (width / 2) + padding;
ctx.moveTo(topLeft, padding);
ctx.bezierCurveTo(topLeft, pull, bottomLeft, height - pull, bottomLeft, height);
ctx.stroke(); }

现在,当我们仍然在draw()函数中时,让我们添加一个新变量来表示形状的起始点,然后添加一个for循环来创建一个可以容纳数据值集合的新变量。以下是变量和循环代码:Var topStartingPoint = 0; for(var i in data) { var group = data[i]; var color = colors[ i % colors.length ];ctx.strokeStyle = color

通过创建一个嵌套的for循环,将一组数据值传递给一个名为line的新变量来进一步操作:for(var j in group) { var line = group[j];然后我们可以在创建一个初始值为零的bottomStartingPoint变量后进行操作:var bottomStartingPoint = 0

第三个嵌套的for循环将允许我们进一步控制形状的定位和移动:for(var k in flatData) { if(flatData[k][1] < line[1]) { bottomStartingPoint += flatData[k][0] + 11;} }

最后,我们使用 link 来设置线条的顶部和底部起始点,link(topStartingPoint, bottomStartingPoint, line[0]);,然后将topStartingPoint赋值为其当前值加上线条数组。最后的语句将topStartingPoint值设置为其当前值加上五:topStartingPoint += line[0]; } topStartingPoint += 5; }}。保存脚本文件。

在浏览器中打开文件random-animation-with-audio.html,您应该会看到线条来回摆动,类似于以下截图所示:

https://github.com/OpenDocCN/freelearn-html-css-js-zh/raw/master/docs/h5-vid-hwt/img/1048_07_10.jpg

它是如何工作的…

首先,我们创建了一个 HTML5 页面,其中包含指向在页面加载时导入的 JavaScript 和 CSS 文件的链接:<script type="text/javascript" src="img/animatedlines.js"></script><link rel="stylesheet" href="css/stylesheet.css" type="text/css" media="screen" charset="utf-8" />。为了激活我们的动画序列,我们将init()函数放在 HTML 页面的 body 标签中。当页面加载时,animatedLines.js JavaScript 文件中的init()函数将通过<body onLoad="init();">进行初始化。

我们使用body样式来设置页面的全局默认margin0background-colorfont colorfont-family。我们为基本链接颜色设置了样式,然后对h1标题标签进行了样式设置,以便它以position: absolute; top: 0的方式显示在top位置,并通过将z-index设置为50始终显示在大多数其他内容块的上方。#credits div 被定位在页面的右下角,音频标签使用visibility: hidden进行隐藏。

我们创建了一个名为animatedLines.js的新脚本,并首先定义了一系列变量和函数来控制形状的行为。

我们设置了一个名为flatten的数组,它会将新值添加到自身。接下来,我们需要一个函数来随机旋转数组的值。我们使用了Math.floor(Math.random()语句来计算一个随机数,并将结果乘以变量top + 1的当前值的总和。然后我们将一个整数值返回给变量current

我们通过使用document.getElementById在页面加载时获取canvas元素的 ID 来定义canvas变量的尺寸值。我们使用 DOM 的帮助设置了canvas变量的widthheight属性:canvas.height = window.innerHeight - 100; ctx = canvas.getContext('2d');然后创建了一个语句,对canvas2d上下文应用了lineJoin,参数为round。我们使用setInterval()函数将线条在画布上绘制的速度设置为300毫秒。数字越大,动画看起来越慢。我们为浏览器窗口添加了一个监听器,以便检测窗口的大小和画布。

然后使用draw()函数将形状绘制到画布上。使用globalCompositeOperation = "darker"来使线条在相互移动时变暗。线条在画布舞台前部重叠时,使用globalCompositeOperation = "lighter"来设置画布背景的外观。

用于装饰线条的颜色需要以rgba格式。rgba 中的’a’指的是 alpha 值,控制每种颜色的可见性。每个 rgba 值集合都包含在一个数组中,然后成为数组列表。我们需要与线条相匹配的宽度和高度值集合。这些存储在数组var data中。

接下来,我们将data数组分配给从我们的shuffle()函数返回的值,以便我们可以随机化屏幕上线条的外观。然后,我们将从flatten()函数返回的值分配给变量flatData。为每条线分配一个拉动值使我们能够将其移动指定数量的像素。我们将这与bezierCurve结合起来,使线条弯曲。

还有更多…

将音频标签、画布动画和 JavaScript 结合起来,听起来像是一种有趣的方式来创建酷炫的可视化效果。然而,这些效果在很大程度上依赖于浏览器的支持,因此许多网络浏览器用户目前无法正确查看它们。我的意思是,大多数标准浏览器在一两年内都无法播放它们。

使用尖端浏览器可视化您的音频

如果您已经下载了测试版的 Firefox 4,您就可以访问 Firefox 音频和视频 API。您将能够使用类似 Spectrum Visualizer 的工具查看和创建自己的音频可视化效果:

www.storiesinflight.com/jsfft/visualizer/index.html

推动 HTML5 中音频的实现

Alexander Chen 一直在尝试使用音频和画布来移植基于 Flash 的应用程序。他在博客中详细介绍了使用多个音频文件时遇到的一些问题:

blog.chenalexander.com/2011/limitations-of-layering-html5-audio/

另请参阅

画布和

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适合人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结合实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值