`
webcode
  • 浏览: 5910982 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

HTML5基础

 
阅读更多

HTML5基础,第1部分:初试锋芒

2011-07-0816:54:02902浏览|6评论

(译者注:由于yeeyan编辑器对文章中的标签做解析的原因,我在每个标签的<符号之后都加入了一个空格,比如说,左尖括号<+section+右尖括号>,我会写成<section>,以便其能够在文章中正确显示,不便之处敬请谅解。)

HTML5是一种设计来组织web内容的语言,其目的是通过创建一种标准的和直观的UI标记语言来把web设计和开发变得容易起来。HTML5提供了各种切割和划分页面的手段,其允许你创建的切割组件不仅能用来逻辑地组织站点,而且能够赋予网站聚合的能力。HTML5可谓是“信息到网站设计的映射方法”,因为它体现了信息映射的本质,划分信息,并给信息加上标签,使其变得容易使用和理解。这是HTML5富于表现力的语义和实用性美学的基础,HTML5赋予设计者和开发者各种层面的能力来向外发布各式各样的内容,从简单的文本内容到丰富的、交互式的多媒体无不包括在内。

HTML5提供了高效的数据管理、绘制、视频和音频工具,其促进了web上的和便携式设备的跨浏览器应用的开发。HTML5是驱动移动云计算服务方面的发展的技术之一,因为其允许更大的灵活性,支持开发非常精彩的交互式网站。其还引入了新的标签(tag)和增强性的功能,其中包括了一个优雅的结构、表单的控制、API、多媒体、数据库支持和显著提升的处理速度等。

HTML5中的新标签都是能高度关联唤起的,标签封装了它们的作用和用法。HTML的过去版本更多的是使用非描述性的标签,然而,HTML5拥有高度描述性的、直观的标签,其提供了丰富的能够立刻让人识别出内容的内容标签。例如,被频繁使用的<div>标签已经有了两个增补进来的<section>和<article>标签。<video>、<audio>、<canvas>和<figure>标签的增加也提供了对特定类型内容的更加精确的描述。

HTML5提供了:

1.确切描述了其旨在要包含的内容的标签
2.增强的网络通信
3.极大改善了的常用存储
4.运行后台进程的WebWorker
5.在本地应用和服务器之间建立持续连接的WebSocket接口
6.更好的存储数据检索方式
7.加快了的页面保存和加载速度
8.对使用CSS3来管理GUI的支持,这意味着HTML5可以是面向内容的
9.改进了的浏览器表单处理
10.基于SQL的数据库API,其允许客户端的本地存储
11.画布和视频,可在无需安装第三方插件的情况下添加图形和视频
12.GeolocationAPI规范,其通过使用智能功能来纳入移动云服务和应用
13.增强型的表单,其降低了下载JavaScript代码的这种必要性,允许在移动设备和云服务之间进行更多高效的通信。

HTML5创建了一种更吸引用户的体验:使用HTML5设计的页面能够提供类似于桌面应用的体验。HTML5还通过把API功能和无处不在的浏览器结合起来的的方式提供了增强的多平台开发。通过使用HTML5,开发者能够提供一种顺畅地跨越各个平台的现代应用体验。

当你说HTML5这个词的时候,你使用了一个简短的词来表达一种持续的创新。新的标记、新的一套方法,以及一个基于HTML5和它的两个与之互为补充的同仁:CSS3和JavaScript之间的相互作用的通用开发框架,这是以客户为中心的处理现象的应用的核心。除了HTML5技术的技巧和方法的许多桌面部署之外,HTML5还可以在功能丰富的web移动电话浏览器中实施——移动电话浏览器是一个正在增长的市场,AppleiPhone、GoogleAndroid和运行PalmwebOS的手机的普及以至于无处不在就可以证明这一点。

HTML5的强大功能中很重要的一面是信息的映射——或说是内容块化(contentblocking)。如果你愿意的话——这种做法会产生一种容易理解得多的处理过程。你可以看到,通过日益增加对web处理这一领域的控制,这一工具在设计和开发方面已经变得多么的高效。

HTML5预示着这样一些情况的出现,即其在文本层面上有着更高效的语义处理,以及在表单构造和用法上有着更强大的控制。所有的这些特性和HTML5创新的其他许多细微之处是这一越来越占统治地位的范式的基础。许多机构实体,商业的和其他的——甚至许多根本不把信息的处理和通信作为他们的主要机构活动的组织——都不同程度地被这一不断增长的现象的发展所侵袭。

HTML5并不是一盏神灯,不会有精灵出现。然而,它的技术和方法资产使得其成为了一件次好的东西,仅次于擦亮一盏神灯这件事情。

规划页面

你将要创建一个简单的web页面。在这一过程中,我会讨论几个HTML5中引入的新标签。为了创建一个高效的并且是有实效的web页面,你必须要制定一个计划,考虑一下想要打造的所有组件。你创建的网页将会有如图1所示的高层设计,页面的设计包含了一个Header区、一个Navigation区、一个包含了三个Section区和一个Aside区的Article区,以及最后的一个Footer区。该页面的设计目标是在Google的Chrome浏览器中工作,其消除了一些视觉上的混乱,这些混乱带来的是浏览器兼容问题的调整,同时也妨碍到了对基础结构的理解。我们的目标是创建出一个清晰地描述了新的HTML5标签的用法的页面,展示如何使用它们来创建格式良好的代码和优雅的页面设计。

图1.AcmeUnited的网页的规划

在创建这一页面的过程中,我会涉及CSS3,我需要用它来正确地渲染HTML5网页。CSS3对于HTML5页面的的风格、导航和一般观感来说是必不可少的,它的一些属性组,你可以在WsSchool的CSS3参考站点(参见参考资料一节)上找到这些属性,其中包括了一些很有用的元素,比如说background、font、marquee和animation等。

不过,在开始构造页面之前,你需要学习一些新的HTML5的标签。

Header区

Header区的例子包含了页面标题和副标题,<header>标签被用来创建页面的Header区的内容。除了网页本身之外,<header>标签还可以包含关于<section>和<article>的公开信息。这里创建的网页有该页面的一个Header区,这在高层设计中有给出,以及一个位于Article和Section区内部的Header区。清单1提供了一个<header>标签标记的例子。

清单1.<header>标签的例子

<header>
<h1>标题文字</h1>
<p>文本或是图像可放在这里</p>
<p>Logo通常也放在这个地方</p>
</header>

<header>标签还可以包含一个<hgroup>标签,如清单2所示。<hgroup>标签把标题分组放在一起,使用<h1>到<h6>这些标题分级来在此处显示主标题和子标题。

清单2.<hgroup>标签的例子

<header>
<hgroup>
<h1>主标题</h1>
<h2>子标题</h2>
</hgroup>
<p>文本或是图像可放在这里</p>
</header>

Navigation区

你可以使用<nav>标签来创建页面的Navigation区。<nav>元素定义了一个专门用于导航的区域,<nav>标签应该用做主站点的导航,而不是用来放置被包含在页面的其他区域中的链接。Navigation区可以包含诸如清单3所示的代码。

清单3.<nav>标签的例子

<nav>
<ul>
<li><ahref="#"kesrc="#">Home</a></li>
<li><ahref="#"kesrc="#">AboutUs<a></li>
<li><ahref="#"kesrc="#">OurProducts</a></li>
<li><ahref="#"kesrc="#">ContactUs</a></li>
</ul>
</nav>

Article和Section区

你设计的页面包含了一个Article区,该区域存放了页面的实际内容。你使用<article>标签来创建这一区域,该标签定义的内容可独立于页面中的其他内容使用。例如,如果想创建一个RSS源(RSSfeed)的话,那么你可以使用<article>来唯一标识该内容。<article>标签标识了可被删除、可被放置在另一上下文中,并且是可被完全理解的内容。

AcmeUnited规划中的Article区包含了三个Section区,可使用<setction>标签来创建这几个区域。<section>包含了web内容的相关组件区域,<section>标签——以及<article>标签——可以包含页眉、页脚,或是其他需要用来完成该部分内容的组件。<section>标签用于分组的内容,<section>标签和<article>标签通常以一个<header>为开始并以一个<footer>结束,标签的内容则放在这两者之间。

<section>标签也可以包含<article>标签,就像<article>标签可以包含<section>标签一样。<section>标签应该用来分组相类似的信息,而<article>标签则应该是用来放置诸如一篇文章或是博客一类的信息,这些内容可在不影响内容含义的情况下被删除或是被放置到新的上下文中。<article>标签,正如它的名称所暗示的那样,提供了一个完整的信息包。相比之下,<section>标签包含的是有关联的信息,但这些信息自身不能被放置到不同的上下文中,因为这样的话其所代表的含义就会丢失。

<article>和<section>标签的用法例子请参见清单4。

清单4.<article>标签和<section>标签的例子

<article>
<section>
Content
</section>
<section>
Content
</section>
</article>
<section>
<article>
Content
</article>
<article>
Content
</article>
</section>

图像元素

<section>和<article>标签这两者,以及<header>和<footer>标签都可以包含<figure>标签,你使用该标签来加入图像、图表和照片。

<figure>标签可以包含<figcaption>,该标签相应的包含了包含在<figure>标签中的图形的标题,其允许你输入描述,把图形和内容更加紧密的关联起来。清单5提供了一个<figure>和<figcaption>标签结构的例子。

清单5.<figure>和<figcaption>标签的例子

<figure>
<imgsrc="/figure.jpg"kesrc="/figure.jpg"width="304"height="228"alt="Picture">
<figcaption>Captionforthefigure</figcaption>
</figure>

媒体元素

<section>和<article>标签还可以包含各种媒体元素,HTML5提供的标签立刻就传达了其内容的意思。媒体元素,比如说音乐和视频,以前只能嵌入,但现在能够被更精准地标识出来。

<audio>标签标识了声音内容,比如说音乐或是任何的其他音频流。<audio>标签有一些属性用来控制音频的内容、何时以及如何播放等方面的情况,这些属性分别是:src、preload、control、loop和autoplay。在清单6给出的例子中,只要页面一加载音频就开会播放,其会持续播放,所提供的控制可以让用户停止或是重新开始播放音频。

清单6.<audio>标签的例子

<audiosrc="MyFirstMusic.ogg"kesrc="MyFirstMusic.ogg"controlsautoplayloop>
Yourbrowserdoesnotsupporttheaudiotag.
</audio>

<video>标签允许你播放视频片段或是流化视觉媒体。其拥有<audio>标签所有的属性,另外再加上三个:poster、width和height。当视频正在加载或是视频处于完全没有加载的糟糕情况中时,poster属性可让你找出一张图像来应付着先。

清单7提供了一个<video>标签结构的例子

清单7.标签的例子

<videosrc="MyFirstMovie.ogg"kesrc="MyFirstMovie.ogg"controls="controls">
Yourbrowserdoesnotsupportthevideotag
</video>

<video>和<audio>标签可以包含<source>标签,该标签定义了<video>和<audio>标签的多媒体资源。使用这一元素,你可以指定替代的视频或是音频文件,然后浏览器就可以基于它的媒体类型或是所支持的编解码器来从中进行选择。清单8中有两种选择,如果文件的WMA版本不能在所使用的浏览器中播放的话,就再尝试MP3版本。否则的话就显示信息,这样用户就知道为什么音频不可用了。

清单8.<source>标签的例子

<audio>
<sourcesrc="/music/good_enough.wma"kesrc="/music/good_enough.wma"type="audio/x-ms-wma">
<sourcesrc="/music/good_enough.mp3"kesrc="/music/good_enough.mp3"type="audio/mpeg">
<p>YourbrowserdoesnotsupporttheHTML'audio'element.</p>
</audio>

<embed>标签定义了可带入到页面中的嵌入式内容——例如,一个AdobeFlashSWF文件的插件。清单9包含了type属性,标明嵌入的资源为Flash文件。

清单9.<embed>标签的例子

<embedsrc="MyFirstVideo.swf"kesrc="MyFirstVideo.swf"type="application/x-shockwave-flash"/>

除了src和type属性之外,<embed>标签还拥有height和width属性。

Aside区

AcmeUnited规划中的Aside区可通过使用<aside>标签来创建。这一标签被看作是用来存放补充内容的地方,这些内容不是其所补充的一篇连续文章的组成部分。在杂志上,插入语(aside)通常被用来突出文章本身所制造的一个观点。<aside>标签包含的内容可被删除,而这不会影响到包含了该内容的文章、章节或是页面所要传达的信息。

清单10提供了<aside>标签用法的一个例子。

清单10.<aside>标签的例子

<p>MyfamilyandIvisitedEuroDisneylastyear.</p>
<aside>
<h4>DisneyinFrance</h4>
<p>BesidesEuroDisney,thereisaDisneylandinCalifornia.</p>
</aside>

Footer区

<footer>元素包含了与页面、文章或是部分内容有关的信息,比如说文章的作者或是日期。作为页面的页脚,其有可能包含了版权或是其他重要的法律信息,如清单11所示。

清单11.<footer>标签的例子

<footer>
<p>Copyright2011AcmeUnited.Allrightsreserved.</p>
</footer>

构建页面

现在你已经了解了需要用来创建一个HTML5页面的基本标签,让我们开始构建你的页面。你会为AcmeUnited构建一个网页,完成后的页面如图2所示,该页面可以下载供你使用(参见下载一节)。

图2.AcmeUnited的网页

那么,让我们把页面装配起来吧。首先要处理的是这个<!doctype>,在HTML5中,<!doctype>被简化了:所有你需要记住就是html。这不仅是简化了这一标签的条目,而还把它变得更适应未来的发展。需要注意的是,它不是被称为html5,就只是html。不管来来去去的有多少个HTML版本,<!doctype>可以一直都是html。

<html>标签包含了所有除了<!doctype>标签之外的其他HTML元素,其他的每一个元素都必须嵌套在<html>和</html>标签之间,参见清单12。

清单12.<!doctype>标签的例子

<!doctypehtml>
<htmllang="en">

在指出了html和语言为英语之后,你就可以使用<head>元素,该元素可以包含脚本、浏览器支持信息、样式表链接、meta信息和其他的初始化函数。你可以在head这一区域中使用这些标签:

1.<base>
2.<link>
3.<meta>
4.<script>
5.<style>
6.<title>

<title>标签存放文档的实际标题,这是一个必需的<head>区元素,它的内容就是你在浏览该页面时会在浏览器的顶端看到的标题。清单13中的<link>标签标识了会被用来渲染HTML5页面的CSS3样式表,样式表的文件名为main-stylesheet.css。

清单13.<head>标签的例子

<head>
<title>HTML5FundamentalsExample</title>
<linkrel="stylesheet"href="main-stylesheet.css"kesrc="main-stylesheet.css"/>
</head>

接下来你会用到<body>标签,后面跟着<header>和<hgroup>标签,这已经在前面介绍过。本例中的<h1>区域包含了虚构公司的名称:AcmeUnited,<h2>区域包含了让你知晓副标题是“ASimpleHTML5Example”的信息,清单14显示了这一标记。

清单14.<body>标签和<header>标签的例子

<body>
<header>
<hgroup>
<h1>AcmeUnited</h1>
<h2>ASimpleHTML5Example</h2>
</hgroup>
</header>

到目前为止,被用来设置页面的CSS3如清单15所示。首先,你建立页面的字体,然后量身定做页面的主体,明确主体的维度,然后设计header段结构的第一级和第二级标题标签,这些是你要给页面使用的header。

清单15.CSS3例子1

*{
font-family:LucidaSans,Arial,Helvetica,sans-serif;
}

body{
width:800px;
margin:0emauto;
}

headerh1{
font-size:50px;
margin:0px;
color:#006;
}

headerh2{
font-size:15px;
margin:0px;
color:#99f;
font-style:italic;
}

清单16展示了<nav>标签,其目的是处理主站点的导航。

清单16.<nav>例子

<nav>
<ul>
<li><ahref="#"kesrc="#">Home</a></li>
<li><ahref="#"kesrc="#">AboutUs</a></li>
<li><ahref="#"kesrc="#">ContactUs</a></li>
</ul>
</nav>

HTML5还有一个<menu>标签——一个给一些设计者和开发者带来混乱的标签。这一混乱源于导航条通常被称为“导航菜单”。<menu>标签在HTML的4.01版本中被弃用,但在HTML5中又死里复生,目的是用来增强交互性。它不应该用来做主导航。唯一应该用来做主导航的标签是<nav>标签,你迟一些就会在本例中用到<menu>标签。

导航的格式化问题由CSS3来处理。清单17中给出的每个<nav>标签的定义都代表了<nav>标签内的<ul>和<li>元素的一个特定状态。

清单17.CSS3例子2

navul{
list-style:none;
padding:0px;
display:block;
clear:right;
background-color:#99f;
padding-left:4px;
height:24px;
}
navulli{
display:inline;
padding:0px20px5px10px;
height:24px;
border-right:1pxsolid#ccc;
}

navullia{
color:#006;
text-decoration:none;
font-size:13px;
font-weight:bold;
}

navullia:hover{
color:#fff;
}

接下来是Article区,这一区域由<article>标签来定义,其中包括了其自己的<header>信息。包含在<article>中的<section>也包含了一个自己的的<header>标签,参见清单18。

清单18.<article>和<section>的例子

<article>
<header>
<h1>
<ahref="#"kesrc="#"title="Linktothispost"rel="bookmark">ArticleHeading</a>
</h1>
</header>
<p>PrimumnonnocereadvitamParamus...</p>
<section>
<header>
<h1>Thisisthefirstsectionheading</h1>
</header>
<p>Scientiapotentiaestquanocentdocentp...</p>
</section>

清单19展示了渲染这一格式的CSS3标记,可以注意到,段落、header和section区的定义都定义在包含了它们的<article>标签上。这里定义的<h1>标签和页面级别定义的<h1>标签有着不同的格式。

清单19.CSS3例子3

article>headerh1{
font-size:40px;
float:left;
margin-left:14px;
}

article>headerh1a{
color:#000090;
text-decoration:none;
}

article>sectionheaderh1{
font-size:20px;
margin-left:25px;
}

articlep{
clear:both;
margin-top:0px;
margin-left:50px;
}

<article>中包含的第二个<section>标签包含了与第一个<section>相同的基本信息,但这一次你要用到一个<aside>、一个<figure>、一个<menu>和一个<mark>标签,参见清单20。

这里使用<aside>标签来表示的信息并非是围绕着它的那些连续内容的组成部分。<figure>标签包含了一个Stonehenge的图片。<section>标签还包含了一个<menu>标签,该标签被用来创建使用了四个缪斯女神的名字来命名的按钮。当某个按钮被点击时,其提供相应缪斯女神的的信息。<mark>标签被用在<p>标签中,以此来突出显示veni、vidi和vici等词。

清单20.<article>和<section>的例子

<section>
<header>
<h1>Secondsectionwithmark,aside,menu&figure</h1>
</header>
<pclass="next-to-aside">...<mark>veni,vidi,vici</mark>.Mater...</p>
<aside>
<p>Thisisanasidethathasmultiplelines....</p>
</aside>
<menulabel="File">
<buttontype="button"onClick="JavaScript:alert('Clio...')">Clio</button>
<buttontype="button"onClick="JavaScript:alert('Thalia...')">Thalia</button>
<buttontype="button"onClick="JavaScript:alert
('Urania...')">Urania</button>
<buttontype="button"onClick="JavaScript:alert
('Calliope...')">Calliope</button>
</menu>
<figure><imgsrc="stonehenge.jpg"kesrc="stonehenge.jpg"alt="Stonehenge"width="200"height="131"/>
<figcaption>Figure1.Stonehenge</figcaption>
</figure>
</section>

这一部分的CSS3包括了一个新的<p>标签的定义,该标签有着比为页面所设的宽度更小的宽度。这种改动允许aside浮在右边而又不会遮盖到文字。清单21显示了这一标记。

清单21.CSS3例子4

articlep.next-to-aside{
width:500px;
}

article>sectionfigure{
margin-left:180px;
margin-bottom:30px;
}

article>section>menu{
margin-left:120px;
}

asidep{
position:relative;
left:0px;
top:-100px;
z-index:1;
width:200px;
float:right;
font-style:italic;
color:#99f;
}

视频部分的元素

这是<article>的最后一个组件:视频部分。例子视频是ogg格式的,在页面被载入后就自动播放,不断循环,并提供暂停和播放控制。在当前的许多实际情况中,ogg视频使用的是ogv(v表示视频)扩展名,如清单22所示。<audio>标签以同样的方式工作。

清单22.<article>和<section>的例子

<section>
<header>
<h1>Thisisavideosection</h1>
</header>
<p><videosrc="http://people.xiph.org/~maikmerten/demos/BigBuckBunny.ogv"kesrc="http://people.xiph.org/~maikmerten/demos/BigBuckBunny.ogv"
controlsautoplayloop>
<divclass="no-html5-video"><p>Thisvideowillworkin
MozillaFirefoxorGoogleChromeonly.</p>
</div>
</video></p>
</section>
</article>

清单23提供了video部分的CSS3定义。

清单23.CSS3例子5

article>sectionvideo{
height:200px;
margin-left:180px;
}

article>sectiondiv.no-html5-video{
height:20px;
text-align:center;
color:#000090;
font-size:13px;
font-style:italic;
font-weight:bold;
background-color:#99f;
}

页面的页脚和结束部分如清单24所示。

清单24.<footer>标签的例子

<footer>
<p>Copyright:2011AcmeUnited.Allrightsreserved.</p>
</footer>
</body>
</html>

页脚的CSS3如清单25所示。

清单25.CSS3例子5

footerp{
text-align:center;
font-size:12px;
color:#888;
margin-top:24px;
}

结论

网页的构建完成结束了这一多部分组成的系列的第一部分。本篇文章的目的是介绍新的HTML5机制。HTML5不仅是HTML4的一个升级:它还是一种新的数字化通信方式。借助于CSS3和JavaScript的功能,HTML5接近于在一个伪包中为开发者提供了全部的一切。如果你愿意从已有的大量的HTML5信息中吸取你所需的内容来,并把它们用到我们的常见做法中的话,那么你将会加入到这一个由称职的的HTML5多媒体web设计者和开发者组成的正在不断壮大的军团中。这一系列的下一篇文章将着眼于如何编写和格式化HTML5的表单。

HTML5基础,第2部分:组织页面的输入

2011-07-1114:33:30979浏览|3评论

窗体顶端

窗体底端

HTML5反映了在网络上和在云端实施业务的方式的巨大变化。本篇文章是一个由四个部分构成的系列的第二部分,该文章系列旨在寻找并突出说明HTML5中的变化。其开始先介绍新的标签和页面的组织,接着提供一些网页设计方面的高层面信息,然后是表单的创建,以及API的使用及其价值所在,最后是Canvas提供的一些颇具创意的可能做法。这一第二部分介绍了HTML5表单控制的概念,并涉及了JavaScript和CSS3在其中发挥的作用。

(译者注:由于yeeyan编辑器对文章中的标签做解析的原因,我在每个标签的<符号之后都加入了一个空格,比如说,左尖括号<+fieldset+右尖括号>,我会写成<fieldset>,以便其能够在文章中正确显示,不便之处敬请谅解。)

企业级机构的管理、数据分析、营销策略以及其他功能都很重要,然而,如果没有合格的数据窗口可提供给你的潜在客户使用的话——或是激发起用户的使用兴趣的话——那么促使站点访问者转化所必需的最初过程就是缺失的。一种积极的、鼓励交互的、用户友好的体验是机构的主要目标,而这种交互是需要你的努力来达成的。

交互的核心是站点的表单,这些表单方便了与用户的互动交流,因此,最初引发网站构建的目标可通过转化站点访问者来推进。表单是活跃网站所有者或是代理商和网站用户之间的交互的核心因素,正因为如此,它们在设计和开发网站过程中就显得极为重要。

核心的核心部分是控件——单选按钮、复选框、文本框、数字的微调控制器等等。对于与站点进行对话的网站用户来说,这些元素都是必不可少的。换句话说,没有充分的功能控制(在“机械”的控件操作和控件适合于给定任务两方面都是),就不可能进行对话,其结果就是,没有潜在的转化。

对转化过程的关系做仔细的考虑是很有必要的,这其中包括了站点访问者和运行系统之间的交互的各个方面,验证的速度、输入、认知、导航、页面的加载以及页面组装的方式,所有的这些方面都对转化过程产生影响。随着HTML5规范的多媒体特性和所提供的扩充的种种表单控件选项一起到来的是验证的改进和增强,这两方面都在HTML5的把站点访问者转化成实际的站点用户的能力中做出了贡献。

对于验证以及完善的基于web的计算——一个关键的安全资产,对于这两方面来说,HTML5是一个异常有力的工具。在设计和开发旨在招徕客户的网站时,其显得越发的重要。因此,它的使用对于维护一个好的转化率来说是必不可少的。如果你不能描绘出前景,那说明你有困惑;但如果你不能转化你所描绘的前景的话,那就得要求紧急迫降了。

不过没关系,这里就能够提供帮助。HTML5的类型,比如说email和telephone,提供了更广泛的通信选项,其与HTML5的语义基础所赋予的结构化清晰度相结合,使得不会再有什么壁垒存在于你和其他一切的畅通对话之间。

鉴于我们的以网络为中心的世界、随机性日益增强的全球经济的忙碌步伐、云计算的快步发展、移动技术使用的呈指数增长,以及跨平台的通信解决方案——既指商业的也指社会的——很明显,我们正站在一个基于web的计算和通信的美丽新世界的门槛上。这一世界是通信的许多元素与IT之间这种不断进化的联姻的函数和导数,同时也是一个高度竞争的全球社会的需要。

设计表单

在HTML5中,表单已经做了重大的修整,一些以前需要JavaScript编码的任务现在已经可以在不需要编码的情况下就很容易地完成。本文中的表单例子分析了HTML5的表单创新套件的用法,当然,这一过程的第一步是规划表单。

你要开发的表单例子的布局如图1所示,你要开发表单页面的三个区域:Header区、Form区和Footer区。Header区包含了封装在<header></header>标签中的页面标题和副标题。在页面的底部,Footer区包含了放在<footer></footer>标签内的版权信息。我已经在这一文章系列的第一部分所提供的例子中讨论了Header区和Footer区的构造,如果你对<header>和<footer>标签不太熟悉的话,请参阅该篇文章。

图1.表单页面的布局

对这一表单的讨论重点放在四个标签上:

1.<form>
2.<fieldset>
3.<label>
4.<input>

在HTML5中,两个新的属性被加入到了<form>标签中:autocomplete和novalidate。autocomplete属性启用了出现在诸如Google一类的站点中的下拉建议列表,novalidate属性关掉表单的校验,这在测试过程中是很有用的。<fieldset>标签有三个新的属性:disable、name和form。disable属性禁用<fieldset>,name属性设置<fieldset>的名称,form属性的值是是<fieldset>所属的一个或多个表单的ID。在HTML5中,<fieldset>可处在其所属的一个或多个表单的外部,当<fieldset>被置于表单的外部时,你必须要设置该<fieldset>标签的form属性,这样<fieldset>就可以正确地与一个或多个表单关联起来。

定义输入元素的类别的<label>标签有一个新的属性:form,form属性的值是<label>所属的一个或多个表单的ID。<label>标签也可放置在表单的外部,因此这里的form属性也是用来把<label>标签和适当的表单关联在一起的。

<input>标签有几个新的类型,以及一些新的属性,这些都增强了表单的可用性。HTML5引入了几个新的input类型,目的是组织和分类数据,复制出HTML5的整个语义路径。形式应该服从内容这句古训很适合于描述HTML5的表单功能。

在HTML5中,表单的<input>域可以处在<form>标签的外部,form属性标识了输入域所属的一个或多个表单,其还可以通过引用form的ID来标识其所属的表单。表1给出了新的<input>类型。

表1.新的<input>类型

colordatedatetimedatetime-localmonth
weektimeemailnumberrange
searchtelurl

表2给出了新的<input>属性

表2.新的<input>属性

autocompleteautofocus  form  formactionformenctype
formmethodformnovalidate formtargetheight max
min multiple   pattern placeholderrequired
step

在网页的创建过程中,你会用到这些类型和属性的大部分。

创建表单

图2所示的是ClassicalMusicPlace的网页,一个提供几个作曲家的作品的下载站点,它还允许古典音乐爱好者上传他们的古典作品录音,这就是你要创建的页面。

图2.ClassicalMusicPlace的表单

表单的结构从<form>标签开始,在该例子中,你用到了新的autocomplete属性,如下所示:

<formid="orderForm"autocomplete="on"action="javascript:alertValues();"method="get">

这一<form>标签中还包含了一个JavaScript式的action,我们会在稍后的内容中谈到这一点。

<form>标签包含了四个<fieldset>标签,其通过图2中的灰色区域很直观地划分了出来:CustomerInfo、FavoriteComposer、Composers和Uploadfile(s)(译者注:原文为Name,Telephone,Emailaddress,anddate,疑有误)。<fieldset>标签分组了表单中的相似内容,让我们看到的是各自分隔开的每个<fieldset>。

第一个<fieldset>标签

第一个<fieldset>标签包含了客户信息(参见图3),它有一个Name域,一个Telephone域,一个Emailaddress域和一个Date域。Name域有一个autofocus属性,其可让你在无需用鼠标点击该域的情况下就可以开始输入文本。

图3.客户信息域

第一个<fieldset>首先包含了一个<legend>,一个<label>和一个<input>标签,如清单1所示。Name域的类型是text,其有三个新的<input>属性:placeholder、autofocus和required。

清单1.Name域

<fieldset>
<legend>CustomerInfo</legend>
<p>
<label>Name:
<inputid="name"name="name"type="text"placeholder="Enteryourname"
autofocusrequiredsize="50">
</label>
</p>

autofocus确保在页面打开时,输入焦点落在该域上。这是一个促成页面只要一加载就获得焦点的功能,其允许用户立刻访问表单。placeholder属性把双引号中的文字以一种柔和的灰色文本的方式显示在域中,placeholder属性应该告诉用户该域要包含的内容,以及当该域为空时所显示的内容。然而,因为Name域还设置了autofocus,所以在进入页面时,你实际上并不能看到这一文本内容。需要注意的是,在图3中,Name域不会显示占位内容,而是有一个黄色的高亮外框。如果你在不输入数据的情况下移到另一个域上的话,占位内容就会显示出来。当autofocus属性和placeholder属性一起使用时,因为该域获得激活焦点的原因,占位内容就会隐而不见。

required属性方便了作为提交表单的先决条件的域的强制性填充。对于text、search、URL、tel、email、password、日期选择器、number、复选框、单选按钮和file等类型来说,该属性都是有效的。

Telephone域的类型是tel,其用到属性required、placeholder、size和pattern,如清单2所示。tel是一个文本域,目的是用来存放电话号码。在这一例子中,电话有着一个必须严格遵守的模式限制,因为除非是你使用了正确的字符模式,否则系统是不会让你提交的。电话的占位符内容存放了你的输入必须与之相匹配的模式。

模式(pattern)模拟了传统的JavaScript正则表达式(regex)的功能,输入的内容必须要与所定义的正则表达式的模式结构相匹配才能通过校验。pattern属性可用在text、search、url、tel、email和password等类型上。

清单2.Telephone域

<p>
<label>Telephone:
<inputid="tel"name="telephone"type="tel"placeholder="Pattern:1-234-567-8910"
requiredsize="50"pattern="([0-9]{1}(-[0-9]{3})(-[0-9]{3})(-[0-9]{4}))">
</label>
</p>

Emailaddress(邮件地址)域的类型是email,如清单3所示。邮件地址是自动进行验证的,无需使用模式:这一验证是HTML5的组成部分。如果邮件地址没有以正确的方式给出的话,表单就不能提交。

清单3.Emailaddress域

<p>
<label>Emailaddress:
<inputid="email"name="email"type="email"placeholder="Enteryouremailaddress"
requiredsize="50">
</label>
</p>

这一<fieldset>的最后一项录入是Date域。date类型会在Opera浏览器中提供一个用于日期选择的日历选择器,但在GoogleChrome中则是创建一个微调器,如图3所示。图4显示了Opera使用Date域的选择器作为显示的网页渲染。可以注意到,在Opera中,域设置框的边角不是圆形的,即使是使用了那种在Chrome中会使边角变圆的的式样表也是如此。

图4.Date域

清单4给出了用来创建日期选择器的代码。

清单4.Date域

<p>
<label>Date:<inputtype="date">
</label>
</p>
</fieldset>

你可以生成任何日期的一个单子,你甚至可以把日期分解到小时一级。下面这些是你可以创建的日期类型:

1.日期:选择日、月和年
2.月份:选择月和年
3.星期:选择星期和年
4.时间:选择时间(小时和分钟)
5.日期时间:选择时间、日、月和年(UTC时间)
6.当地日期时间:选择时间、日、月和年(当地时间)

第二个<fieldset>标签

第二个<fieldset>标签包含了一个用到了list属性的<input>标签和一个<datalist>标签。list属性指明了输入域的<datalist>,<datalist>标签提供了一个输入域选项列表。list属性可用在这些<input>类型上:text、search、url、tel、email、日期选择器、number、range和color。

<datalist>以下拉列表的方式做显示,如图5所示。这一截图是从Opera中获取的,在Chrome中,该列表只是显示成一个简单的文本框,没有把列表呈现给用户。

图5.Favorites域

清单5提供了创建FavoriteComposer部分的域设置。

清单5.FavoriteComposer域

<fieldset>
<legend>FavoriteComposer</legend>
<p>
<label>
<inputtype="text"name="favorites"list="composers">
<datalistid="composers">
<optionvalue="Bach">
<optionvalue="Beethoven">
<optionvalue="Brahms">
<optionvalue="Chopin">
<optionvalue="Mendelssohn">
</datalist>
</label>
</p>
</fieldset>

第三个<fieldset>标签

第三个<fieldset>标签显示了作曲家的一个列表,后面跟随着一个数字域,该域指明了每位列出的作曲家都提供了多少作品。图6显示该部分内容。

图6.Composers域

例如,Bach有五个作品,Beethoven有十个作品。清单6给出了每个作曲家作品个数的最大值,在你提交表单时,数字域不会接受超过最大值的数值。在提交时,该域通过提示你改正输入来响应不正确的、超出范围的值,这样它就能够遵照该域的可接受数值的限制。

number类型创建了一个输入的微调域,其用到了min、max和step属性。默认的step值是1。min、max和step属性可用来做number、range和日期选择器的输入限制。max属性决定输入域所允许的最大值,min属性决定输入域所允许的最小值,step属性决定有效的递增值。

清单6.Composer域

<fieldset>
<legend>Composers</legend>
<p>
<label>
Bach:<inputname="form_number"id="form_number"type="number"min="1"max="5">
</label>
</p>
<p>
<label>
Beethoven:<inputname="form_number"id="form_number"type="number"
min="1"max="10">
</label>
</p>
<p>
<label>
Brahms:<inputname="form_number"id="form_number"type="number"min="1"max="7">
</label>
</p>
<p>
<label>
Chopin:<inputname="form_number"id="form_number"type="number"min="1"max="10">
</label>
</p>
<p>
<label>
Mendelssohn:<inputname="form_number"id="form_number"type="number"
min="1"max="4">
</label>
</p>

</fieldset>

第四个<fieldset>标签

第四个<fieldset>标签包含了file类型的<input>并用到了属性multiple,如图7所示。multiple属性指明了输入域可以从数据列表或是文件列表中选择多个值,用户可以选择多个上传的文件。

图7.Upload域

file类型和multiple属性的代码如清单7所示。

清单7.Upload域

<fieldset>
<legend>Uploadfile(s)</legend>
<p>Uploadoneofyourorchestra'sfile(s)forinclusioninourlibrary</p>
<p><label>
<inputtype="file"multiple="multiple"/>
</label>
</p>
</fieldset>

Submit按钮用到了height和width属性,如清单8所示。你使用这些属性来设置image输入类型的高和宽。在设置这些属性时,页面为图像预留的空间区域由这一预设的宽度和高度尺寸所强制执行的约束来确定,这种做法通过增强页面渲染的功效来使页面的加载变得更顺利。

清单8.Submit按钮

<inputtype="image"src="submitbutton.png"kesrc="submitbutton.png"alt="Submit"width="100"height="45"/>
</form>

JavaScript和CSS3

没CSS3的话,HTML5的渲染就无法完成。而且,尽管HTML5已经排除了对一些JavaScript编码的需要,但JavaScript依然是一个很有用的工具。下面是用来创建例子表单的JavaScript代码和CSS3文件。

JavaScript代码是一个返回三个必输入域的警告框,如清单9所示。尽管这里用到的JavaScript代码只有一行,但它被放置在一个单独的JavaScript文件中,遵循使用JavaScript的最佳做法。

清单9.JavaScript代码的例子

functionalertValues()
{
alert("Customerinformation:"+"\n"+fullname.value+"\n"
+tel.value+"\n"+email.value);
}

清单10展示了用来格式化例子表单的CSS3代码,这里不包括<header>和<footer>的信息。

清单10.例子表单的CSS3

form{
width:550px;
margin:0000;
padding:50px60px;
background-color:#2d2d2d;
border-radius:20px;
}

fieldset{
padding:020px20px;
margin:0030px;
border:2pxsolid#ffffff;
background:#B8B8B8;
border-radius:10px;
}

legend{
color:#ffffff;
background:#990033;
font-size:0.9em;
font-weight:bold;
text-align:left;
padding:5px;
margin:0;
width:10em;
border:2pxsolid#660033;
border-radius:5px;
}

label{
display:block;
float:left;
clear:left;
text-align:left;
width:100%;
padding:.4em000;
margin:.15em000;
}

结论

切实的个人和机构的成功的关键是沟通。表单控件和一般网页的构造指南对这一过程来说很重要。HTML5提供了一盒子适合于这一任务的功能非常强大的工具。那些有为将来做准备的人——现在已经到时候了——将会受益,而那些没有做准备的人则将会受到这个世界一网化的(one-Web-world)、以网络为中心的全球化社会的步伐和需求的严重冲击。

GraceWalker是位于伊利诺斯州的芝加哥的WalkerAutomatedServices公司的合伙人,她是一位有着多重背景和丰富经验的IT顾问。她在IT行业担任过经理、管理员、程序员、讲师、业务分析师、技术分析师、系统分析师和Web开发者,工作的背景环境也各不相同,其中包括了电信、教育、金融服务和软件等。

HTML5基础,第3部分:HTML5API的威力

2011-07-1315:56:54878浏览|0评论

(译者注:由于yeeyan编辑器对文章中的标签做解析的原因,我在每个标签的<符号之后都加入了一个空格,比如说,左尖括号<+head+右尖括号>,我会写成<head>,以便其能够在文章中正确显示,不便之处敬请谅解。)

那么,什么是API呢?

应用编程接口(applicationprograminterface,API)是访问一个软件应用的编程指令和标准的集合。通过使用API,你就可以设计出由API提供的服务来驱动的产品。

HTML5拥有一些新的API,例如:

1.一个与新的画布元素一起使用的2D绘图API,用于渲染图形或是其他的视觉图像
2.一个支持离线web应用的缓存机制的API
3.一个播放视频和音频的API,与新的视频和音频元素一起使用
4.一个历史记录API,其把浏览历史变成可访问的,并允许把页面添加到这一历史中
5.一个和draggable属性一起使用的拖放API
6.一个和contenteditable属性一起使用的编辑API
7.键-值对以及内嵌的SQL数据库的客户端存储,使用了JavaScriptAPI

本篇文章重点关注两个API:Geolocation和WebWorker,首先对这些API本身进行分析,然后创建一个包含这两个API的页面。

无处不在的业务:Geolocation

GeolocationAPI被用来确定和分享地理位置,API返回经度和纬度坐标——这是企业可用来在这一坐标附近的区域提供服务的信息,这类服务通常被称作基于位置的服务(location-basedservice,LBS)。

LBS以地理数据源为参考,这些地理数据源被用来标识被监控仪器的物理位置,从而识别出与这一位置相关的人。这一功能赋予感兴趣的各方与这一个人进行交互的机会,这种交互是基于一些以地理位置为中心的兴趣点市场来进行的。

商业实际上是为客户创造品质、实用性和价值,并同时为利益相关者、债权人、股东、员工和供应商创造经济和金融利益。以地理位置为驱动力的LBS使得跟踪和监控一个包裹或是使用了非浏览器设备或是浏览器的个人变得相当容易起来。从商业化的角度来说,地理位置所涉及的就是使用地理资产来确定某人或是某物所处的位置,然后把这一特定的一组信息出售给想要把这些信息用于社会、商业或是其他目的的的任何人,只要信息的拥有者的这种做法是法律许可的就可以了。

地理定位(geolocation)的工作方式

GeolocationAPI基于navigator这一全局对象的一个新属性:navigator.geolocation,这一JavaScript的navigator对象提供了一些关于访问者的浏览器和系统的有用信息。Geolocation可以确定使用了IP地址、基于web的数据库、无线网络连接,以及三角定位或是GPS技术的访问者的经度和纬度。应该要注意的一点是,由Geolocation提供的信息的准确性会基于获取信息的手段而发生变化。偶然情况下,在一些位置上,你有可能不能获得明确的地理位置读数或是一点数据都接收不到。

脚本可使用navigator.geolocation对象来确定与用户的宿主设备相关的位置信息,在检索到位置信息之后,一个位置对象就会被创建出来,并使用这些数据做填充。

navigator.geolocation对象有三个方法:

1.getCurrentPosition()
2.watchPosition()
3.clearWatch()

getCurrentPosition()方法

getCurrentPosition()方法检索用户的当前位置,但只检索一次。当该方法被脚本调用时,方法以异步的方式来尝试获取宿主设备的当前位置。异步通信意味着发送者和接收者并未同时地加入到这一通信过程中,使用异步通信能让浏览器继续进行其他方面的活动,这样它就无需等待来自接收实体的响应。

getCurrentPosition()方法最多可以有三个参数:

1.geolocationSuccess:带回当前位置的回调(callback)(必需的)
2.geolocationError.有错误发生时使用的回调(可选的)
3.geolocationOptions.地理位置选项(可选的)

navigator.geolocation.getCurrentPositon()方法使用一个Position对象作为参数来把宿主设备的当前位置返回给geolocationSuccess这一回调,如果有错误发生的话,geolocationError回调会使用一个PositionError对象来做调用。你可以设置geolocationOptions的三个属性:enableHighAccuracy、timeout和maximumAge,这些可选属性相应的作用分别是启用了高的精确性,如果设备支持这种高精确性的话;一个超时时段,这是位置应该被返回的最长等待时间;以及一个最大的时间数,缓存的位置在这一时间段内可被使用。

getCurrentPosition()方法的调用如下所示:

voidnavigator.geolocation.getCurrentPosition(
geolocationSuccess,geolocationError,geolocationOptions);

watchPosition()方法

watchPosition()方法定期轮询用户的位置,查看用户的位置是否发生改变。其最多可带三个参数。

当watchPosition被调用时,其异步地启动一个查看过程,这一过程涉及了一个新的Position对象的获取和一个watchID的创建。如果这一获取操作是成功的,则相关的使用一个Position对象作为参数的geolocationSuccess就会被调用。在失败时涉及的操作则是使用一个非空的geolocationError参数来调用该方法,watchPosition方法使用一个PositionError对象作为参数来生成geolocationError。当设备的位置发生改变时,一个合适的带有新的Position对象的回调就会被调用。

watchPosition()方法的调用如下所示:

longnavigator.geolocation.watchPosition(
geolocationSuccess,geolocationError,geolocationOptions);

clearWatch()方法

clearWatch()方法终止正在进行的watchPosition(),该方法只能带一个参数。在调用时,其找到之前已经开始了的watchID参数并立即停止它。

clearWatch()方法的调用如下所示:

voidnavigator.geolocation.clearWatch(watchID)

Geolocation数据:Position对象

GeolocationAPI返回一个地理上的Position对象,该对象有两个属性:timestamp和coords。timestamp属性表示地理位置数据的创建时间,coords属性又包含七个属性:

1.coords.latitude:估计纬度
2.coords.longitude:估计经度
3.coords.altitude:估计高度
4.coords.accuracy:所提供的以米为单位的经度和纬度估计的精确度
5.coords.altitudeAccuracy:所提供的以米为单位的高度估计的精确度
6.coords.heading:宿主设备当前移动的角度方向,相对于正北方向顺时针计算
7.coords.speed:以米每秒为单位的设备的当前对地速度

这些属性中只有三项是保证有的:coords.latitude、coords.longitude和coords.accuracy,其余的返回null,这取决于设备的能力和其所采用的后端定位服务器。如果可能的话,heading和speed属性可以基于用户之前的位置计算出来。

发挥救援作用的webworker

webworker(web工作线程)补救了并发所引起的问题,webworker是HTML5家族对JavaScript的单线程问题的回答:它们在与主页面分开的线程中运行处理过程,保留页面以用于主要的功能,比如说维持一个稳定的UI等。

一个webworker是一个在后台加载并执行的JavaScript文件,这些worker允许你动态地加载一个JavaScript,然后使用后台的不会影响到UI的进程来执行脚本。webworker的访问是受限的,其只允许传递字符串。因为webworker不使用浏览器的UI线程,所以他们不允许访问DOM。worker可以使用这两个worker全局范围的self和this引用,worker和父页面的通信是通过使用事件模型和postMessage()方法来实现的。

因为webworker有多线程行为,因此它们只能访问JavaScript功能的一个子集,webworker可以:

1.访问navigator对象
2.使用只读的位置对象
3.执行XMLHttpRequest以发送HTTP或是HTTPS请求
4.使用setTimeout()/clearTimeout()和setInterval()/clearInterval()来设置时间或是时间间隔
5.访问应用的缓存
6.使用importScripts()方法来导入外部的脚本
7.产生其他的webworker(子worker(subworker)必需有着与主页面一样的来源,且必须放置于与父worker同样的地点。)

webworker有两种类型:专用型的worker和共享型的worker。

专用型webworker

专用型worker与创建它的脚本链接在一起,它可以与其他的worker或是浏览器组件通信,但是他不能与DOM通信。

专用型worker的创建方法是把一个JavaScript文件名传递给一个新的worker实例,通过指定worker的执行脚本URI来使用Worker()构造函数创建一个新的worker。要创建一个专用型worker的话,输入下面给出的代码,这一代码创建了一个新的专用的Worker对象:

varworker=newWorker('worker.js');

共享型webworker

共享型webworker和专用型worker一样,不能访问DOM,并且是受限地访问窗体的属性。共享型webworker只能与其他来自同一个域的共享型webworker通信,它的创建方法是把一个JavaScript名称传递给一个新的共享型worker的实例来创建。

页面脚本可以与共享型webworker通信,而然,与专用型webworker不同的是,通信是通过使用一个端口(port)对象并附加上一个消息事件处理程序来进行的。另外,在使用第一个postMessage()之前,你必须要调用端口的start()方法。

在收到webworker脚本的首个消息之后,共享型webworker把一个事件处理程序附加到激活的端口上。一般情况下,处理程序会运行自己的postMessage()方法来把一个消息返回给调用代码,接着端口的start()方法生成一个有效的消息进程。

为了创建一个共享型webworker,你必须要创建一个SharedWorker对象而不是一个Worker对象。下面的代码说明了如何创建一个新的SharedWorker对象:

varworker=newSharedWorker('worker.js');

构造一个包含了这两个API的页面

你将设计一个包含了Geolocation和WebWorkerAPI的基本工作模式的页面,此外,你还会用到GoogleMapAPI来渲染作为地图收集来的数据。

页面的组织如图1所示,其包含了一个使用<header></header>标签来创建的Header区,一个使用<section></section>标签来创建的Section区,以及一个使用<aside></aside>标签来创建的Aside区。

图1.API页面的布局

<section>和<aside>区包含了API,Section区包含了GeolocationAPI,Aside区包含了webworker,其用来计算素数。

在执行时,网页的显示如图2所示。如果要查看地理位置数据的话,你首先必须要同意共享你的信息。webworker在页面加载时启动,如果你想看一看找到的素数的话,点击DisplayWebWorker按钮。

图2.API网页

HTML文件

HTML文件一开始的内容是清单1所示的标准的HTML5信息,<head>部分包含了一个到GoogleMapsAPI的调用,把sensor的值设置为False。使用GoogleMapsAPI对你状态的要求是,你的应用是否在使用一个传感器,比如说GPS来确立位置。你必须为你的GoogleMapsAPI应用声明一个值为True或是False的sensor参数,sensor的值必须被声明。<head>标签还包含了到JavaScript和CSS3文件的链接,这些文件被用来处理网页的功能和格式。

清单1.HTML文件开始部分的内容

<!doctypehtml>
<html>
<head>
<title>BasicGeoLocationMap&WebWorkerPrimeNumberCalculator</title>
<scriptsrc="http://maps.google.com/maps/api/js?sensor=false"kesrc="http://maps.google.com/maps/api/js?sensor=false"
type="text/javascript"></script>
<LINKhref="GeolocationWebWorker.css"kesrc="GeolocationWebWorker.css"rel="stylesheet"type="text/css">
<scriptsrc="HTML-Part3-GeolocationWebWorker.js"kesrc="HTML-Part3-GeolocationWebWorker.js"type="text/javascript"></script>
</head>

<body>标签包含了onLoad事件,该事件调用地理定位的初始化函数,如清单2所示。该函数检验地理定位是否可在这一浏览器中使用,这一初始化函数放在JavaScript文件中。如果浏览器可以和GeolocationAPI通信的话,地图就会被渲染。

清单2.初始化Geolocation

<bodyonLoad="initGeoApp();">
<header>
<hgroup>
<h1>Geolocation&WebWorker</h1>
<h2>Makingitwork</h2>
</hgroup>
</header>

清单3中给出的<section>标签包含了navigator.geolocation对象的输出显示信息,API返回的经度和纬度被用来创建地图画布,Position的coords数据也通过使用<span></span>标签显示出来。

清单3.Geolocation的地图和位置

<section>
<p>Thisisthegeolocationexamplemap.</p>
<divid="map_canvas"></div>

<p>Thisistheoutputfromthenavigator.geolocationobject.</p>
<table>
<tr>
<td>accuracy:</td>
<td><spanid="accuracyOutput"></span></td>
</tr>
<tr>
<td>altitude:</td>
<td><spanid="altitudeOutput"></span></td>
</tr>
<tr>
<td>altitudeAccuracy:</td>
<td><spanid="altitudeAccuracyOutput"></span></td>
</tr>
<tr>
<td>heading:</td>
<td><spanid="headingOutput"></span></td>
</tr>
<tr>
<td>latitude:</td>
<td><spanid="latitudeOutput"></span></td>
</tr>
<tr>
<td>longitude:</td>
<td><spanid="longitudeOutput"></span></td>
</tr>
<tr>
<td>speed:</td>
<td><spanid="speedOutput"></span></td>
</tr>
</table>
</section>
<aside>
<p>ThisistheWebWorker.</p>
<p>Primenumbercalculationresult:
<outputid="result"></output></p>

WebWorker计算素数,<output>这一新的标签被用来显示webworker提供的计算结果,<output>标签中的ID与JavaScript用来标识其要执行的计算的ID是相同的。在<span>和<output>标签中用到的ID使得它们在DOM中是可访问的,没有引用ID的话,JavaScript就不知道要使用哪一个<span>和<output>。清单4给出了webworker的输出。

清单4.webworker的输出

<aside>
<p>ThisistheWebWorker.</p>
<p>Primenumbercalculationresult:
<outputid="result"></output></p>

<input>中用到的onClick首先显示由素数(PrimeNumber)webworker计算出来的值,而第二个onClick则是被用来停止webworker的。清单5给出了代码。在按钮被点击时,displayWorker()函数引发显示webworker计算出来的结果。webworker在页面载入后开始计算素数。

清单5.webworker的input标签

<inputtype="button"value="DisplayWebWorker"onClick="displayWorker();">
<inputtype="button"value="StopWebWorker"onClick="stopWorker();">

</aside>
</body>
</html>

JavaScript文件

JavaScript是例子页面上展示的API背后的引擎,GeolocationAPI是通过调用initGeoApp()函数来初始化的,这就是由<body>标签中的onLoad()事件来执行的函数:其决定了你的浏览器是否能够使用地理位置数据(参见清单6)。如果你的浏览器可以使用地理位置数据的话,则GeolocationAPI就会被调用。如果调用成功的话,就会使用Position中的属性值来绘制地图,然后属性的值会接在地图的后面打印出来。

清单6.Geolocation的函数

functioninitGeoApp()
{
if(navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(success,failure);
}
else
{
alert("Yourbrowserdoesnotsupportgeolocationservices.");
}
}

基于你在HTML文件中提供的ID,document.getElementById被用来检索值。document.getElementById是文档对象的一个方法,应该通过使用document.getElementById来访问,如清单7所示。Position的属性值存放在这里,这样它们就能够用来在要渲染的地图下面打印属性。

清单7.使用getElementById来获取coords的值

varmap;
functionsuccess(position)
{
document.getElementById("accuracyOutput").innerHTML=
position.coords.accuracy;
document.getElementById("altitudeOutput").innerHTML=
position.coords.aktitude;
document.getElementById("altitudeAccuracyOutput").innerHTML=
position.coords.altitudeAccuracy;
document.getElementById("headingOutput").innerHTML=
position.coords.heading;
document.getElementById("latitudeOutput").innerHTML=
position.coords.latitude;
document.getElementById("longitudeOutput").innerHTML=
position.coords.longitude;
document.getElementById("speedOutput").innerHTML=
position.coords.speed;

接下来的这部分定义的是GoogleMapAPI的LatLng对象的坐标,如清单8所示。GoogleMapAPILatLng对象提供了需要用来创建地图的坐标信息,你可以设置缩放级别和其他的几个选项,这些选项创建了呈现给用户的地图的外观。

清单8.GoogleMap的选项

varcoordinates=newgoogle.maps.LatLng(position.coords.latitude,
position.coords.longitude);

varmyOptions=
{
zoom:14,
center:coordinates,
mapTypeControl:false,
navigationControlOptions:{style:google.maps.NavigationControlStyle.small},
mapTypeId:google.maps.MapTypeId.ROADMAP
};

注意一下mapTypeID这一选项,该选项选择的是ROADMAP,该值所呈现的地图的样子如图2所示。该选项有四个可选的值:

1.ROADMAP
2.HYBRID
3.SATELLITE
4.TERRAIN

图3给出了选择HYBRID选项时网页看起来的样子。

图3.使用混合式地图的API网页。

map_canvas这一ID被用来创建地图,该ID是HTML文件中的<div>的ID。

map=newgoogle.maps.Map(document.getElementById("map_canvas"),myOptions);

在地图上放一个初始位置的标记,清单9给出了这一代码。

清单9.放置一个初始的地图标记

varmarker=newgoogle.maps.Marker({
position:coordinates,
map:map,
title:"Youarehere."
});
}

functionfailure()
{
alert("Sorry,couldnotobtainlocation");
}

webworker在页面初始化之后就开始执行。如果用户想要显示所执行的计算的输出的话,他/她可以点击DisplayWebWorker按钮,这将会调用displayWorker()函数。清单10给出了它的代码。

清单10.webworker

varworker=newWorker('PrimeNumberWebWorker.js');

functiondisplayWorker()
{
worker.onmessage=function(event)
{
document.getElementById('result').innerHTML=event.data;
};
}

如果用户想要停止webworker的话,他/她可以点击StopWebWorker按钮,这会调用清单11中给出的stopWorker()函数。

清单11.终止worker

functionstopWorker()
{
worker.terminate();
}

webworker文件

该文件是素数计算器的webworker,其计算出每个素数直到被终止执行。清单12给出了它的代码。

清单12.计算素数

varn=1;
search:while(true){
n+=1;
for(vari=2;i<=Math.sqrt(n);i+=1)
if(n%i==0)
continuesearch;
postMessage(n);
}

CSS3文件

清单13中给出的CSS3文件提供了HTML5页面中显示的格式。

清单13.CSS3描述

*{font-family:Arial,Helvetica,sans-serif;
}

body{
margin:0300px0300px;
color:#990000;
background-color:#FFFFCC;
}

header>hgrouph1{
margin:003px0;
padding:0;
text-align:center;
font-size:30px;
}


header>hgrouph2{
margin:0015px0;
padding:0;
text-align:center;
font-style:italic;
font-size:12px;
}


headerp{
margin:0020px0;
padding:0;
text-align:center;
font-size:12px;
}

aside{
width:200px;
height:175px;
margin:-450px00450px;
background-color:#990000;
padding:.5px0010px;
color:#FFFFFF;
font-weight:bold;
}

div{
width:400px;
height:250px;
}

结论

文章系列的这一部分内容研究了Geolocation和WebWorkerAPI的实用性。选择这两个API是因为把它们放在一起既说明了API使用的创新性又说明了实际上的可用性。对于HTML5规范在创建新的业务模型方面的使用来说,Geolocation是一个很好的例子。同样,WebWorker的角色是JavaScript的并发性所固有的一些问题的解决方案。

这两个API共同说明了一种用于商业和社会的HTML5使用模式的组合,因此,它们的功效说明了HTML5富互联网应用的特有便利性和一般管理手段。

HTML5基础,第4部分:点睛之笔Canvas

2011-07-1612:49:58399浏览|0评论

窗体顶端

窗体底端

HTML5反映了在网络上和在云端实施业务的方式的巨大变化。本篇文章是一个由四个部分构成的系列的第三部分,该文章系列旨在寻找并突出说明HTML5中的变化。本部分内容介绍了HTML5的Canvas元素,并使用了几个例子来说明该元素的功能。

(译者注:由于yeeyan编辑器对文章中的标签做解析的原因,我在每个标签的<符号之后都加入了一个空格,比如说,左尖括号<+head+右尖括号>,我会写成<head>,以便其能够在文章中正确显示,不便之处敬请谅解。)

使用HTML5来编写代码的人,有着设计者和开发者双重身份的强悍组合,其职责是构造出高效的富互联网应用(richInternetapplication,RIA),特别是丰富的用户界面。就高效这个字眼来说,我的意思是指系统级的和系统性的创造力增强,这种增强以数字化的方式促进了站点所有者、所有者的代理机构和站点用户之间的对话。

RIA是用户获得满意体验的来源之处和媒介,因此,它是任何成功的以网络为中心的风险投资的重要组成部分。以网络为中心的活动,就性质来说,或多或少都是协作式的。公司要在包括了市场营销和管理的各个层面都取得成功的话,数字化协作的制胜方法是至关重要的。很多时候的很多情况都取决于效率,网站要依靠效率来满足其访问者的品质期望。

正如你已经见到的那样,HTML5是为这一具有跨平台能力、融合了通信、使用统一语言、提供无处不在的计算,以及基于开放系统的协作式“一网化世界(onewebworld)”量身定做的。这一文章系列的前面三部分内容重点关注语义、正确的编码方法、输入在极为重要的转化过程中的作用,以及站点管理最佳做法等,所有这些的目的都是在为以一种有组织和符合逻辑的方式来创建RIA奠定基础。每篇文章中都共有的一个主题是,对于实现网站所有者的机构目标来说,制造并管理丰富的用户体验是至关重要的。

什么是Canvas?

HTML5Canvas(画布)是一个非常有用的绘图和动画元素,Canvas使用JavaScript来直接在页面上绘制图形。这是一个由你来定义和控制的长方形区域,该区域允许动态、可脚本渲染的2D图形和位图图像。

在制作用来增强UI、示意图、相册、图表、图形、动画和嵌入式绘图应用的那些非常棒的视觉材料方面,HTML5堪称完美。Canvas元素有一些用来绘制路径、矩形、圆形和字符的方法。

Canvas的坐标

在画布上绘图的一个先决条件是要熟悉网格或是坐标空间,宽度和高度的空间区域测量是以像素为单位给出的。画布是基于x和y坐标的使用来构建的,画布的x=0,y=0坐标位于左上角。

画布的矩形区域的默认属性是300像素的宽度和150像素的高度,但你可以通过指定宽度和高度来确定画布元素的确切大小。图1中的示意图说明了x和y坐标的实现方式。

图1.Canvas的坐标

图1给出了一个100像素X100像素的画布区:

1.左上角是x=0,y=0。

2.x的值水平增加,y的值垂直增加。

3.右下角是x=100,y=100。

4.中间的点是x=50,y=50。

开始第一步

要在画布上放置任何东西的话,你首先必须在HTML文件中定义画布。你必须创建访问<canvas>标签的JavaScript代码,并通过与HTML5CanvasAPI通信来绘制你的图像。

<canvas>标签的基本结构如下:

<canvasid="myCanvas"width="200"height="200"></canvas>

canvas元素自身有两个属性:width和height,除此之外,canvas还拥有所有主要的HTML5属性,比如说class、id和name等。id属性被用在上面所示的代码中,JavaScript使用这里创建的canvas的id来表示要在上面绘画的画布。JavaScript使用document.getElementById()方法来确定正确的画布,如下面代码所示:

varcanvas=document.getElementById("myCanvas");

每个画布都必须要有一个context(上下文)的定义,如下面代码所示。就目前的情况来说,官方规范只承认一个2D环境:

varcontext=canvas.getContext("2d");

在标识画布并指明了它的上下文之后,你就做好了开始绘画的准备了。

绘图工具、效果和转换

在HTML5Canvas的这一讨论过程中,我们对各种绘图工具、效果和转换都查看一番。绘图工具包括:

1.线条
2.矩形
3.圆弧
4.贝塞尔曲线和二次曲线
5.圆和半圆

你会用到的Canvas效果包括:

1.填充和描边
2.线性和径向的渐变

要讨论的转换包括:

1.缩放
2.旋转
3.平移

绘制线段

要在画布上绘制线段的话,你可以使用moveTo()、lineTo()和stroke()方法,此外,你要使用beginPath()方法来重置当前路径:

1.context.beginPath();
2.Context.moveTo(x,y);
3.Context.lineTo(x,y);
4.Context.stroke(x,y);

beginPath()方法开始一条新的路径,在使用不同的子路径绘制一条新的线段之前,你必须要使用beginPath()来标明一个绘制过程要遵循的新起点。在绘制第一条线段时,beginPath()方法的调用不是必须的。

moveTo()方法指明新的子路径从哪里开始,lineTo()方法创建子路径。你可以使用lineWidth和strokeStyle来改变线段的外观,lineWidth元素改变线段的粗细,strokeStyle改变颜色。

在图2中,三条线段分别用蓝色、绿色和紫色画了出来。

图2.画有三条不同颜色的线段的画布

图2中的线段由清单1中的代码来创建,蓝色的线段有着圆弧形的端点,该线段是由首个context.beginPath()这一开始新路径的建立的方法来创建的,其后紧跟着:

1.context.moveTo(50,50),该方法把线路的起点置于(x=50,y=50)
2.context.lineTo(300,50),该方法标识线段的终点
3.context.lineWidth=10,该属性是线段的宽度
4.context.strokeStyle="#0000FF",该属性是线段的颜色
5.context.lineCap="round",该属性把端点设成是圆弧状的
6.context.stroke(),该方法真正在画布上绘制该线段

所有线段的长度都是50像素,尽管它们看上去不一样长——这是由线段的线帽(linecap)造成的视觉错觉。可用的线帽有三种:

1.Context.round(blue)
2.Context.square(green)
3.Context.butt(purple)——默认值

对接(butt)线帽是默认值,当你使用圆形(round)或是方形(square)的线帽风格时,线段的长度会增加,加上一段相当于线段宽度的长度。例如,一个长度为200像素,宽度为10像素,有着圆形或是方形线帽风格的线段,其最终的线段长度是210像素,因为每个线帽都都往线段的每一端加上了5个像素的长度。而一个长度为200像素,宽度为20像素,有着圆形或是方形的线帽风格的线段的最终长度是220像素,因为每个线帽都往线段每一端加上了10像素的长度。

通过执行和修改清单1中的代码来更好地理解线段的绘制方式。

清单1.在画布上创建三条不同颜色的线段

<!DOCTYPEHTML>
<html>
<head>
<title>LineExample</title>
<style>
body{
margin:0px;
padding:0px;
}

#myCanvas{
border:1pxsolid#9C9898;
}
</style>
<script>

window.onload=function(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

//有着圆形端点的蓝色线段
context.beginPath();
context.moveTo(50,50);
context.lineTo(300,50);
context.lineWidth=10;
context.strokeStyle="#0000FF";
context.lineCap="round";
context.stroke();

//有着方形端点的绿色线段
context.beginPath();
context.moveTo(50,100);
context.lineTo(300,100);
context.lineWidth=20;
context.strokeStyle="#00FF00";
context.lineCap="square";
context.stroke();

//有着对接端点的紫色线段
context.beginPath();
context.moveTo(50,150);
context.lineTo(300,150);
context.lineWidth=30;
context.strokeStyle="#FF00FF";
context.lineCap="butt";
context.stroke();
};
</script>
</head>
<body>
<canvasid="myCanvas"width="400"height="200">
</canvas>

</body>
</html>

绘制矩形

有三个方法可用来在画布上给出一个矩形的区域:

1.fillRect(x,y,width,height),该方法绘制一个有填充的矩形
2.strokeRect(x,y,width,height),该方法绘制一个矩形的外边框
3.clearRect(x,y,width,height),该方法清空指定的区域,使之变得完全透明

对于这三个方法中的每个来说,x和y表示的都是画布上相对于矩形(x=0,y=0)的左上角的位置,width和height分别是矩形的宽度和高度。

图3显示了由清单2中的代码创建的三个矩形。

图3.画有矩形的画布

fillRect()方法创建了一个以缺省的黑色为填充色的矩形;clearRect()方法在第一个矩形的中心部分清除出一个矩形区域,该区域位于由fillRect()方法产生的矩形的中央位置;strokeRect创建了一个只有可见的黑色边框的矩形。

清单2.矩形画布的代码

<!DOCTYPEHTML>
<html>
<head>
<title>RectangleExample</title>
<style>
body{
margin:0px;
padding:0px;
}

#myCanvas{
border:1pxsolid#000000;
background-color:#ffff00;
}
</style>
<scripttype="text/javascript">
functiondrawShape(){
varcanvas=document.getElementById('myCanvas');

varcontext=canvas.getContext('2d');

context.fillRect(25,25,50,50);
context.clearRect(35,35,30,30);
context.strokeRect(100,100,50,50);

}
</script>
</head>
<bodyonload="drawShape();">
<canvasid="myCanvas"width="200"height="200"></canvas>
</body>
</html>

绘制圆弧、曲线、圆和半圆

圆和半圆都是使用arc()方法来绘制,arc()方法用到了六个参数:

context.arc(centerX,centerY,radius,startingAngle,endingAngle,antiClockwise);

centerX和centerY参数是圆的中心坐标,radius就是数学上的半径:从圆心到圆周线的一条直线。弧形是作为所定义的圆的一部分来创建的,startAngle和endAngle参数分别是圆弧的起点和终点,以弧度为单位。anticlockwise参数是一个布尔(Boolean)值,当其值为true时,弧形按逆时针方向来绘制,当其值为false时,弧形按顺时针方向来绘制。

要使用arc()方法来绘制圆的话,把起始角度定义成0,把结束角度定义成2*PI,如下所示:

context.arc(centerX,centerY,radius,0,2*Math.PI,false);

要使用arc()方法来绘制半圆的话,把结束角度定义成startingAngle+PI,如下所示:

context.arc(centerX,centerY,radius,startingAngle,startingAngle+Math.PI,false);

二次曲线

quadraticCurveTo()方法被用来创建一条二次曲线,如下所示。二次曲线通过上下文中的点、一个控制点以及一个结束点来定义。控制点确定了线的曲度。

context.moveTo(x,y);
context.quadraticCurveTo(controlX,controlY,endX,endY);

贝塞尔曲线

正和二次曲线一样,贝塞尔曲线也有一个起点和一个终点,但和二次曲线不同的是,它有两个控制点:

context.moveTo(x,y);
context.bezierCurveTo(controlX1,controlY1,controlX2,controlY2,endX,endY);

你可使用bezierCurveTo()方法来创建贝塞尔曲线,因为贝塞尔曲线是由两个控制点而不仅是由一个控制点来定义的,所有你可以创造出更加复杂的曲度来。

图4的显示——从左到右——为一条圆弧、一条二次曲线、一条贝塞尔曲线、一个半圆和一个圆。

图4.圆弧、曲线和圆

图4的内容是用清单3中的代码来创建的。

清单3.圆弧、曲线和圆的代码

<!DOCTYPEHTML>
<html>
<head>
<title>Arcs,Curves,Circles,&Semicircles</title>
<style>
body{
margin:0px;
padding:0px;
}

#myCanvas{
border:1pxsolid#9C9898;
}
</style>
<script>
functiondrawArc(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

varcenterX=100;
varcenterY=160;
varradius=75;
varstartingAngle=1.1*Math.PI;
varendingAngle=1.9*Math.PI;
varcounterclockwise=false;

context.arc(centerX,centerY,radius,startingAngle,
endingAngle,counterclockwise);

context.lineWidth=10;
context.strokeStyle="black";
context.stroke();
};

functiondrawQuadratic(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

context.moveTo(200,150);

varcontrolX=288;
varcontrolY=0;
varendX=388;
varendY=150;

context.quadraticCurveTo(controlX,controlY,endX,endY);
context.lineWidth=10;
context.strokeStyle="black";
context.stroke();
};

functiondrawBezier(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

context.moveTo(350,350);

varcontrolX1=440;
varcontrolY1=10;
varcontrolX2=550;
varcontrolY2=10;
varendX=500;
varendY=150;

context.bezierCurveTo(controlX1,controlY1,controlX2,
controlY2,endX,endY);

context.lineWidth=10;
context.strokeStyle="black";
context.stroke();
};

functiondrawCircle(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

varcenterX=450;
varcenterY=375;
varradius=70;

context.beginPath();
context.arc(centerX,centerY,radius,0,2*Math.PI,false);

context.fillStyle="#800000";
context.fill();
context.lineWidth=5;
context.strokeStyle="black";
context.stroke();
};

functiondrawSemicircle(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

varcenterX=100;
varcenterY=375;
varradius=70;
varlineWidth=5;

context.beginPath();
context.arc(centerX,centerY,radius,0,Math.PI,false);
context.closePath();

context.lineWidth=lineWidth;
context.fillStyle="#900000";
context.fill();
context.strokeStyle="black";
context.stroke();
};

window.onload=function(){
drawArc();
drawQuadratic();
drawBezier();
drawCircle();
drawSemicircle()
}
</script>
</head>
<body>
<canvasid="myCanvas"width="600"height="500">
</canvas>
</body>
</html>

转换:平移、缩放和旋转

translate()、scale()和rotate()方法都会修改当前的矩阵。translate(x,y)方法把画布上的项目移动到网格上的不同点上,在translate(x,y)方法中,(x,y)坐标指明了图像在x方向和y方向上应该移动的像素数。

如果你使用drawImage()方法来在(15,25)这一位置绘制一个图像的话,你可以使用(20,30)作为参数的来调用translate(),该调用把图像放在(15+20,25+30)=(35,55)这一位置上。

scale(x,y)方法改变图像的大小,x参数指明水平方向的比例系数,y参数指明垂直方向的比例系数。例如,scale(1.5,.75)将创建一个在x方向加大50%,而在y方向只相当于当前尺寸75%的图像。rotate(angle)方法返回一个基于指定角度的对象。

图5是一个可以使用translate()、scale()和rotate()进行渲染的图像例子。

图5.使用转换

清单4提供的代码创建了图5中的图像。

清单4.创建转换的代码

<!DOCTYPEHTML>
<html>
<head>
<Title>TransformationsExample</title>
<script>

window.onload=function(){
varcanvas=document.getElementById("myCanvas");
varcontext=canvas.getContext("2d");

varrectWidth=250;
varrectHeight=75;

//把context平移到画布的中心
context.translate(canvas.width/2,canvas.height/2);

//y方向的组成减半
context.scale(1,0.5);

//顺时针旋转45度
context.rotate(-Math.PI/4);

context.fillStyle="blue";
context.fillRect(-rectWidth/2,-rectHeight/2,
rectWidth,rectHeight);

//水平方向翻转context
context.scale(-1,1);

context.font="30ptCalibri";
context.textAlign="center";
context.fillStyle="#ffffff";
context.fillText("MirrorImage",3,10);

}

</script>
</head>
<body>
<canvasid="myCanvas"width="400"height="400"></canvas>
</body>
</html>

渐变

渐变(gradient)是指从一种颜色向另一种颜色变化的填充,在颜色相交的地方做融合。在Canvas中你可以创建两种类型的渐变:线性的和径向的。

createLinearGradient()方法被用来创建线性的渐变。createLinearGradient(x0,y0,x1,y1)沿着一条由两个点(x0,y0)和(x1,y1)来标识的直线产生一个渐变,这两个点分别是渐变的起点和终点。该方法返回一个对象。

颜色的渐变可以有多种颜色,addcolorStop(offset,color)方法为被标明为在给定的偏移量上渐变的颜色指明了颜色过渡点。addColorStop()方法让你在0和1之间指定一个偏移量,以这一偏移量为依据来开始过渡到下一种颜色。值0是渐变的一端的偏移量,1是另一端的偏移量。在颜色的渐变定义好了之后,渐变对象就可以被赋值给fillStyle()。你也可以使用fillText()方法来绘制出带有渐变的文字来。

径向渐变——createradialGradient(x0,y0,r0,x1,y1,r1)——使用六个参数以一种圆形或是圆锥形的模式来组合两种或多种颜色。

1.(x0,y0):圆锥的第一个圆的中心
2.r0:第一个圆的半径
3.(x1,y1):圆锥的第二个圆的中心
4.r1:第二个圆的半径

图6包含了四种渐变:一个线性渐变、一个文本渐变、一个对角线上的渐变和一个径向渐变。

图6.渐变的例子

图6的内容是使用清单5中的代码创建出来的。

清单5.渐变的例子代码

<!doctype>
<html>
<head>
<title>GradientExample</title>
<script>
window.onload=function(){
varcanvas=document.getElementById("myCanvas");

varcontext=canvas.getContext("2d");

//在一个矩形中尝试做渐变

//创建一个线性渐变
varfillColor=context.createLinearGradient(50,50,150,50);

//设置渐变的颜色
fillColor.addColorStop(0.15,"red");
fillColor.addColorStop(0.35,"black");
fillColor.addColorStop(0.65,"green");
fillColor.addColorStop(0.87,"yellow");

//把渐变对象赋值给fillstyle
context.fillStyle=fillColor;

//绘制矩形
context.fillRect(50,50,100,100);

//使用文本

varfillColorText=context.createLinearGradient(300,50,600,50);

fillColorText.addColorStop(0.2,"red");
fillColorText.addColorStop(0.4,"black");
fillColorText.addColorStop(0.6,"green");
fillColorText.addColorStop(0.8,"yellow");

context.fillStyle=fillColorText;

context.font="40pxverdana";
context.textBaseline="top";
context.fillText("Withtexttoo!",300,50)

//对角线上的渐变
varfillColordiagonal=context.createLinearGradient(50,200,100,450);

//渐变颜色
fillColordiagonal.addColorStop(0.2,"red");
fillColordiagonal.addColorStop(0.4,"black");
fillColordiagonal.addColorStop(0.6,"green");
fillColordiagonal.addColorStop(0.75,"yellow");

//把渐变对象赋值给fillstyle
context.fillStyle=fillColordiagonal;

//绘制矩形
context.fillRect(50,225,100,250);

//绘制径向渐变
fillColorRadial=context.createRadialGradient(450,300,0,450,300,200);
fillColorRadial.addColorStop(0,"red");
fillColorRadial.addColorStop(0.2,"black");
fillColorRadial.addColorStop(0.4,"green");
fillColorRadial.addColorStop(0.7,"yellow");
context.fillStyle=fillColorRadial;
context.rect(300,200,500,400);
context.fill();

}
</script>
</head>
<body>
<div>
<p><canvasid="myCanvas"width="600"height="400"></canvas></p>
</div>
</body>
</html>

图像剪裁

你可以通过裁剪出选定的区域来改变图像。在画布上裁剪是一项重载drawImage()方法的功能,drawImage()有三种选择,你可以使用三个、五个或者是九个参数。

三个参数的配置——drawImage(image,dx,dy)——在目标坐标(dx,dy)上绘制图形。坐标构成了图像的左上角。

五个参数的配置——drawImage(image,dx,dy,dw,dh)——提供了目标的宽度和高度,图像会被缩放以适应目标宽度和高度。

九个参数的配置——drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)——用到一个图像,以图像来源的(sx,sy)坐标为开始剪出一个宽度和高度为(sw,sh)的矩形区域,并把它缩放使之适应目标宽度和高度(dw,dh),然后把它放置在画布的(dx,dy)位置上。

图7显示了你将要对其做剪裁的图像。

图7.剪裁图像

通过利用图7中给出的图像,可以把一组图像放置在画布上。一个图像有画布大小,被用作背景,另一个被创建的图像较小一些,被插入到画布的右下角上,第三个图像是一个切出来的拿破仑的头像,被放置在画布的左上角上。裁剪后的图像的最后情况如图8所示。

图8.最终裁剪出来的图像

图8中的内容是使用清单6中的代码创建出来的。在执行这一代码之前,确保已下载了这一例子中用到的Napolean.png图像

清单6.用来裁剪例子图像的代码

<!doctype>
<html>
<head>
<title>CropExample</title>
<scripttype="text/javascript">
window.onload=function(){
varcanvas=document.getElementById("cropNapolean");
varcontext=canvas.getContext("2d");

varimageObj=newImage();
imageObj.onload=function(){
//绘制图像覆盖整个画布
context.drawImage(imageObj,0,0,600,400);

//在右下角绘制一个小图像
varsourceX=0;
varsourceY=0;
varsourceWidth=1200;
varsourceHeight=801;
vardestX=300;
vardestY=200;
vardestWidth=sourceWidth-900;
vardestHeight=sourceHeight-600;

context.drawImage(imageObj,sourceX,sourceY,sourceWidth,
sourceHeight,destX,destY,destWidth,destHeight);

//只绘制拿破仑的头部
varsourceNapoleanX=460;
varsourceNapoleanY=25;
varsourceNapoleanWidth=250;
varsourceNapoleanHeight=175;
vardestNapoleanX=0;
vardestNapoleanY=0;
vardestNapoleanWidth=sourceNapoleanWidth-150;
vardestNapoleanHeight=sourceNapoleanHeight-100;

context.drawImage(imageObj,sourceNapoleanX,sourceNapoleanY,
sourceNapoleanWidth,sourceNapoleanHeight,
destNapoleanX,destNapoleanY,
destNapoleanWidth,destNapoleanHeight);
}
imageObj.src="Napoleon.png";
}
</script>

</head>
<body>
<div>
<p><canvasid="cropNapolean"width="600"height="400"></canvas></p>
</div>
</body>
</html>

动画和多重画布

要处理动画方面的内容的话,分层问题总是不可避免的。分层允许组件被隔开开来,这使得编码和调试变得更容易且更高效。CanvasAPI并未有分层的处理,但你可以创建多重的画布。

动画必须是随着时间的推移来做控制的,因此,要创建一个动画的话,你需要处理动画的每一帧内容。CanvasAPI在动画方面有一个主要的限制是:在某个形状被放置到画布上之后,它就一直保持它的样子不变了,要移动该形状的话,你必须要重新绘制它。

要创建一个动画的话:

1.清除掉之前在画布上绘制的任何图像。

2.保存画布的状态,确保在每次绘制一个帧的时候都是使用最初的状态。

3.执行渲染帧的步骤。

4.如果你已经保存了状态的话,在绘制新的帧之前恢复该状态。

你可以以两种方式来控制动画:使用setInterval或者setTimeout方法,每个方法都可以用来在超过某个设定时间段时调用一个函数。setInterval函数重复地执行所提供的代码,setTimeout函数只在所提供的时间过去之后执行一次。

图9展示了游泳者的多重画布动画的一帧,水画在一幅画布上,游泳的人则画在另一幅画布上。

图9.用到多重画布的图像的动画

清单7中的代码被用来创建游泳者,代码使用一个线性渐变来创建水的效果。水有四种蓝色色调,这提供了一种合理的水的假象。游泳者的动作通过使用positionX和positionY的值来创建,这两个值改变图像所摆放的样子。游泳者的头使用arc()方法来创建,游泳者的腿和双臂则是通过绘制线段然后改变他们的lineTo()位置来创建,躯干则是通过修改moveTo()的位置来发生变化。因为这是一个动画,因此你需要执行这一段代码来看一下游泳者是如何运动的。

清单7.动画例子

<!DOCTYPEHTML>
<html>
<head>
<title>Animation&MultipleCanvasExample</title>
<script>
//水的画布
functiondrawWater(){
varcanvasWater=document.getElementById("myWaterCanvas");
varcontextWater=canvasWater.getContext("2d");
contextWater.globalAlpha=.50;

//创建一个线性渐变的填充
varlinearGrad=contextWater.createLinearGradient(0,0,400,400);
linearGrad.addColorStop(0,'#0000ff');//setsthefirstcolor
linearGrad.addColorStop(.25,'#0099ff');//setsthesecondcolor
linearGrad.addColorStop(.50,'#00ccff');//setsthethirdcolor
linearGrad.addColorStop(.75,'#00ffff');//setsthefourthcolor
contextWater.fillStyle=linearGrad;
contextWater.fillRect(0,0,400,400);
}

//游泳者的画布
setInterval(drawSwimmer,30);
varpositionX=0;
varpositionY=0;

functiondrawSwimmer(){
varcanvasSwimmer=document.getElementById("mySwimmerCanvas");
varcontextSwimmer=canvasSwimmer.getContext("2d");
contextSwimmer.clearRect(0,0,400,400);

if(positionX<30)
{
positionX+=1;
positionY+=1;
}
else
{
positionX=0;
positionY=0;
}


contextSwimmer.save();

//绘制一个圆作为头部
varcenterX=200;
varcenterY=50;
varradius=20;

contextSwimmer.beginPath();
contextSwimmer.arc(centerX,centerY+positionY,
radius,0,2*Math.PI,false);

contextSwimmer.fillStyle="#000000";
contextSwimmer.fill();
contextSwimmer.lineWidth=5;

//躯干部分
contextSwimmer.beginPath();
contextSwimmer.moveTo(200,70+positionY);
contextSwimmer.lineTo(200,175);
contextSwimmer.lineWidth=10;
contextSwimmer.strokeStyle="#000000";
contextSwimmer.lineCap="round";
contextSwimmer.stroke();

//画右边的手臂
contextSwimmer.beginPath();
contextSwimmer.moveTo(200,100);
contextSwimmer.lineTo(175-positionX,140-positionY);
contextSwimmer.lineWidth=10;
contextSwimmer.strokeStyle="#000000";
contextSwimmer.lineCap="round";
contextSwimmer.stroke();

//画左边的手臂
contextSwimmer.beginPath();
contextSwimmer.moveTo(200,100);
contextSwimmer.lineTo(225+positionX,140-positionY);
contextSwimmer.lineWidth=10;
contextSwimmer.strokeStyle="#000000";
contextSwimmer.lineCap="round";
contextSwimmer.stroke();

//画右边的腿
contextSwimmer.beginPath();
contextSwimmer.moveTo(200,175);
contextSwimmer.lineTo(190-positionX,250-positionY);
contextSwimmer.lineWidth=10;
contextSwimmer.strokeStyle="#000000";
contextSwimmer.lineCap="round";
contextSwimmer.stroke();

//画左边的腿
contextSwimmer.beginPath();
contextSwimmer.moveTo(200,175);
contextSwimmer.lineTo(210+positionX,250-positionY);
contextSwimmer.lineWidth=10;
contextSwimmer.strokeStyle="#000000";
contextSwimmer.lineCap="round";
contextSwimmer.stroke();

contextSwimmer.restore();

};

</script>

</head>
<bodyonload="drawWater();">
<canvasid="myWaterCanvas"width="400"height="400"style="z-index:2;
position:absolute;left:0px;top:0px;">
</canvas>
<canvasid="mySwimmerCanvas"width="400"height="400"style="z-index:1;
position:absolute;left:0px;top:0px;">
</canvas>

</body>
</html>

结论

HTML5的画布是基于浏览器的RIA的结构核心,其提供了一种以JavaScript和你的想像力为驱动力的实用的绘图环境。学习它真的不是很难,并且网络上有许多培训和学习所需的支持工具,其中包括了速查表、博客、在线文章、视频和非视频教程,以及示例应用程序等。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics