精华内容
下载资源
问答
  • HTML5新特性总结大全

    万次阅读 多人点赞 2018-12-20 14:55:13
    (1)HTML5 将成为 HTML、XHTML 以及 HTML DOM 的标准; (2)HTML5 仍处于完善之中。然而,大部分现代浏览器已经具备了某些 HTML5 支持。 2.HTML5的起步: (1)HTML5 是 W3C(World Wide Web Consortium,万维网...

    一.HTML5概念:

    1.什么是HTML5:

    (1)HTML5 将成为 HTML、XHTML 以及 HTML DOM 的新标准;

    (2)HTML5 仍处于完善之中。然而,大部分现代浏览器已经具备了某些 HTML5 支持。

    2.HTML5的起步:

    (1)HTML5 是 W3C(World Wide Web Consortium,万维网联盟) 与 WHATWG 合作的结果

    (2)为 HTML5 建立的一些规则:

    a.新特性应该基于 HTML、CSS、DOM 以及 JavaScript

    b.减少对外部插件的需求(比如 Flash)

    c.更优秀的错误处理

    d.更多取代脚本的标记

    e.HTML5 应该独立于设备

    f.开发进程应对公众透明

    3.新特性:

    (1)用于绘画的 canvas 元素

    (2)用于媒介回放的 video 和 audio 元素

    (3)对本地离线存储的更好的支持

    (4)新的特殊内容元素,比如 article、footer、header、nav、section

    (5)新的表单控件,比如 calendar、date、time、email、url、search

    二.HTML5视频:

    1.Web 上的视频:

    (1)大多数视频是通过插件(比如 Flash)来显示的,然而,并非所有浏览器都拥有同样的插件

    (2)HTML5 规定了一种通过 video 元素来包含视频的标准方法

    2.视频格式:

    (1)Ogg格式:

    带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件

    (2)MPEG4格式:

    带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件

    (3)WebM格式:

    带有 VP8 视频编码和 Vorbis 音频编码的 WebM 文件

    3.如何工作:

    (1)示例代码:

    		<video src="movie.ogg" controls="controls">...</video>
    

    (2)controls 属性供添加播放、暂停和音量控件,可加入宽度和高度, 与 之间插入的内容是供不支持 video 元素的浏览器显示的

    (3)video 元素允许多个 source 元素。source 元素可以链接不同的视频文件。浏览器将使用第一个可识别的格式:

    		<video width="320" height="240" controls="controls">
    			<source src="movie.ogg" type="video/ogg">
    			 <source src="movie.mp4" type="video/mp4">
    		Your browser does not support the video tag.
    		</video>
    

    4.各浏览器对不同格式的支持情况:

    	格式		IE		Firefox		Opera	Chrome	Safari
    	Ogg		No		3.5+		10.5+	5.0+	No
    	MPEG 4	9.0+	No			No		5.0+	3.0+
    	WebM	No		4.0+		10.6+	6.0+	No
    

    5. 标签的属性:

    	属性			值			描述
    
    	autoplay	autoplay	如果出现该属性,则视频在就绪后马上播放
    
    	controls	controls	如果出现该属性,则向用户显示控件,比如播放按钮
    
    	height		pixels		设置视频播放器的高度
    
    	loop		loop		如果出现该属性,则当媒介文件完成播放后再次开始播放
    
    	preload		preload		如果出现该属性,则视频在页面加载时进行加载,并预备播放。如果使用 "autoplay",则忽略该属性
    
    	src			url			要播放的视频的 URL
    
    	width		pixels		设置视频播放器的宽度
    

    三.HTML 5 Video + DOM:

    1.使用 DOM 进行控制:

    (1)HTML5 元素同样拥有方法、属性和事件;

    (2)方法用于播放、暂停以及加载等。其中的属性(比如时长、音量等)可以被读取或设置。其中的 DOM 事件能够通知您,比方说, 元素开始播放、已暂停,已停止,等等

    2.方法、属性以及事件:

    	方法			属性			事件
    
    	play()		currentSrc	play
    
    	pause()		currentTime	pause
    
    	load()		videoWidth	progress
    
    	canPlayType	videoHeight	error
    
    				duration	timeupdate
    
    				ended		ended
    
    				error		abort
    
    				paused		empty
    
    				muted		emptied
    
    				seeking		waiting
    
    				volume		loadedmetadata
    
    				height	 
    
    				width	
    

    在所有属性中,只有 videoWidth 和 videoHeight 属性是立即可用的。在视频的元数据已加载后,其他属性才可用

    四.HTML5 音频:

    1.Web 上的音频:

    (1)大多数音频是通过插件(比如 Flash)来播放的。然而,并非所有浏览器都拥有同样的插件

    (2)HTML5 规定了一种通过 audio 元素来包含音频的标准方法

    (3)audio 元素能够播放声音文件或者音频流

    2.audio 元素支持的三种音频格式:

    	 				IE 9		Firefox 3.5		Opera 10.5		Chrome 3.0		Safari 3.0
    
    	Ogg Vorbis	 					√				√				√	 
    
    	MP3				√	 	 										√				√
    
    	Wav	 							√				√	 							√	
    

    3.如何工作:

    (1)示例代码:

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

    (2)control 属性供添加播放、暂停和音量控件, 与 之间插入的内容是供不支持 audio 元素的浏览器显示的

    (3)audio 元素允许多个 source 元素。source 元素可以链接不同的音频文件。浏览器将使用第一个可识别的格式:

    		<audio controls="controls">
    			 <source src="song.ogg" type="audio/ogg">
    			<source src="song.mp3" type="audio/mpeg">
    		Your browser does not support the audio tag.
    		</audio>
    

    (4) 标签的属性:

    		属性			值			描述
    
    		autoplay	autoplay	如果出现该属性,则音频在就绪后马上播放
    
    		controls	controls	如果出现该属性,则向用户显示控件,比如播放按钮
    
    		loop		loop		如果出现该属性,则每当音频结束时重新开始播放
    
    		preload		preload		如果出现该属性,则音频在页面加载时进行加载,并预备播放。如果使用 "autoplay",则忽略该属性
    
    		src			url			要播放的音频的 URL
    

    五.HTML5 拖放:

    1.拖放(Drag 和 drop)是 HTML5 标准的组成部分:

    (1)拖放是一种常见的特性,即抓取对象以后拖到另一个位置

    (2)在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放

    2.拖动相关设置:

    (1)设置元素为可拖放:

    首先,为了使元素可拖动,把 draggable 属性设置为 true :

    			<img draggable="true" />
    

    (2)规定拖动元素:

    ondragstart 和 setData()

    ondragstart 属性调用了一个函数,drag(event),它规定了被拖动的数据

    dataTransfer.setData() 方法设置被拖数据的数据类型和值:

    			function drag(ev)
    			{
    				ev.dataTransfer.setData("Text",ev.target.id);
    			}
    

    数据类型是 “Text”,值是可拖动元素的 id (“drag1”)

    (3)放到何处 - ondragover:

    ondragover 事件规定在何处放置被拖动的数据;

    默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。

    调用 ondragover 事件的 event.preventDefault() 方法:

    			event.preventDefault()
    

    (4)进行放置 - ondrop:

    当放置被拖数据时,会发生 drop 事件;

    ondrop 属性调用了一个函数,drop(event):

    			function drop(ev)
    			{
    				ev.preventDefault();
    				var data=ev.dataTransfer.getData("Text");
    				ev.target.appendChild(document.getElementById(data));
    			}
    

    (5)注意点:

    a.调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)

    b.通过 dataTransfer.getData(“Text”) 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据

    c.被拖数据是被拖元素的 id (“drag1”)

    d.把被拖元素追加到放置元素(目标元素)中

    3.拖动示例代码:

    	<!DOCTYPE HTML>
    	<html>
    	<head>
    	<script type="text/javascript">
    	function allowDrop(ev)
    	{
    		ev.preventDefault();
    	}
    
    	function drag(ev)
    	{
    		ev.dataTransfer.setData("Text",ev.target.id);
    	}
    
    	function drop(ev)
    	{
    		ev.preventDefault();
    		var data=ev.dataTransfer.getData("Text");
    		ev.target.appendChild(document.getElementById(data));
    	}
    	</script>
    	</head>
    	<body>
    
    	<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    	<img id="drag1" src="img_logo.gif" draggable="true"
    	ondragstart="drag(event)" width="336" height="69" />
    
    	</body>
    	</html>
    

    六.Canvas:

    1.什么是Canvas:

    (1)HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像

    (2)画布是一个矩形区域,您可以控制其每一像素

    (3)canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法

    2.创建canvas元素:

    示例代码:

    		<canvas id="myCanvas" width="200" height="100"></canvas>
    

    3. 通过 JavaScript 来绘制:

    (1)canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:

    		<script type="text/javascript">
    		var c=document.getElementById("myCanvas");
    		var cxt=c.getContext("2d");
    		cxt.fillStyle="#FF0000";
    		cxt.fillRect(0,0,150,75);
    		</script>
    
    		//getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法
    

    (2)使用 id 来寻找 canvas 元素,然后,创建 context 对象,然后进行绘制

    (3)fillRect 方法拥有参数 (0,0,150,75):

    在画布上绘制 150x75 的矩形,从左上角开始 (0,0)

    (4)可以通过canvas绘制出点、线条、圆、渐变背景、图像

    七.内联 SVG:

    1.什么是SVG:

    (1)SVG 指可伸缩矢量图形 (Scalable Vector Graphics)

    (2)SVG 用于定义用于网络的基于矢量的图形

    (3)SVG 使用 XML 格式定义图形

    (4)SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失

    (5)SVG 是万维网联盟的标准

    2.SVG 的优势:

    (1)SVG 图像可通过文本编辑器来创建和修改

    (2)SVG 图像可被搜索、索引、脚本化或压缩

    (3)SVG 是可伸缩的

    (4)SVG 图像可在任何的分辨率下被高质量地打印

    (5)SVG 可在图像质量不下降的情况下被放大

    3.把 SVG 直接嵌入 HTML 页面:

    	<!DOCTYPE html>
    	<html>
    	<body>
    	<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190">
    		  <polygon points="100,10 40,180 190,60 10,60 160,180"
    		  style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" />
    	</svg>
    	</body>
    	</html>
    

    八.Canvas vs SVG:

    1.SVG:

    (1)SVG 是一种使用 XML 描述 2D 图形的语言

    (2)SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器

    (3)在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形

    2.Canvas:

    (1)Canvas 通过 JavaScript 来绘制 2D 图形

    (2)Canvas 是逐像素进行渲染的。

    (3)在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象

    3.Canvas 与 SVG 的比较:

    (1)Canvas:

    依赖分辨率

    不支持事件处理器

    弱的文本渲染能力

    能够以 .png 或 .jpg 格式保存结果图像

    最适合图像密集型的游戏,其中的许多对象会被频繁重绘

    (2)SVG:

    不依赖分辨率

    支持事件处理器

    最适合带有大型渲染区域的应用程序(比如谷歌地图)

    复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)

    不适合游戏应用

    九.地理定位:

    1.定位用户的位置:

    (1)HTML5 Geolocation API 用于获得用户的地理位置

    (2)鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的

    2.使用地理定位:

    (1)使用 getCurrentPosition() 方法来获得用户的位置

    (2)返回用户位置的经度和纬度的代码示例:

    		<script>
    			var x=document.getElementById("demo");
    			function getLocation()
    			{
    			 if (navigator.geolocation)
    			  {
    					navigator.geolocation.getCurrentPosition(showPosition);
    			  }
    			else{x.innerHTML="Geolocation is not supported by this browser.";}
    			 }
    			function showPosition(position)
    			{
    			x.innerHTML="Latitude: " + position.coords.latitude +
    			"<br />Longitude: " + position.coords.longitude;
    			}
    		</script>
    

    (3)示例代码解释:

    检测是否支持地理定位

    如果支持,则运行 getCurrentPosition() 方法。如果不支持,则向用户显示一段消息

    如果getCurrentPosition()运行成功,则向参数showPosition中规定的函数返回一个coordinates对象

    showPosition() 函数获得并显示经度和纬度

    3.处理错误和拒绝:

    (1)getCurrentPosition() 方法的第二个参数用于处理错误。它规定当获取用户位置失败时运行的函数

    (2)示例代码:

    		function showError(error)
    		  {
    			switch(error.code)
    				  {
    					case error.PERMISSION_DENIED:
     					 x.innerHTML="User denied the request for Geolocation."
      					 break;
    					case error.POSITION_UNAVAILABLE:
     					 x.innerHTML="Location information is unavailable."
     					 break;
    				 case error.TIMEOUT:
      					  x.innerHTML="The request to get user location timed out."
    					  break;
    					case error.UNKNOWN_ERROR:
      					  x.innerHTML="An unknown error occurred."
    					  break;
    			 }
    		}
    

    (3)错误代码:

    Permission denied - 用户不允许地理定位

    Position unavailable - 无法获取当前位置

    Timeout - 操作超时

    4.在地图中显示结果:

    (1)如需在地图中显示结果,您需要访问可使用经纬度的地图服务,比如谷歌地图或百度地图

    (2)示例代码:

    		function showPosition(position)
    		{
    			var latlon=position.coords.latitude+","+position.coords.longitude;
    			var img_url="http://maps.googleapis.com/maps/api/staticmap?center="
    			+latlon+"&zoom=14&size=400x300&sensor=false";
    			document.getElementById("mapholder").innerHTML="<img src='"+img_url+"' />";
    		}
    

    5.getCurrentPosition() 方法 - 返回数据:

    (1)若成功,则 getCurrentPosition() 方法返回对象。始终会返回 latitude、longitude 以及 accuracy 属性。如果可用,则会返回其他下面的属性

    (2)属性:

    		属性							描述
    
    		coords.latitude				十进制数的纬度
    
    		coords.longitude				十进制数的经度
    
    		coords.accuracy				位置精度
    
    		coords.altitude				海拔,海平面以上以米计
    
    		coords.altitudeAccuracy		位置的海拔精度
    
    		coords.heading				方向,从正北开始以度计
    
    		coords.speed				速度,以米/每秒计
    
    		timestamp					响应的日期/时间
    

    6.Geolocation 对象 - 其他有趣的方法:

    (1)watchPosition() - 返回用户的当前位置,并继续返回用户移动时的更新位置(就像汽车上的 GPS)

    (2)clearWatch() - 停止 watchPosition() 方法

    十. Web 存储:

    1.在客户端存储数据:

    (1)HTML5 提供了两种在客户端存储数据的新方法:

    localStorage - 没有时间限制的数据存储

    sessionStorage - 针对一个 session 的数据存储

    (2)之前,这些都是由 cookie 完成的。但是 cookie 不适合大量数据的存储,因为它们由每个对服务器的请求来传递,这使得 cookie 速度很慢而且效率也不高

    (3)在 HTML5 中,数据不是由每个服务器请求传递的,而是只有在请求时使用数据。它使在不影响网站性能的情况下存储大量数据成为可能

    (4)对于不同的网站,数据存储于不同的区域,并且一个网站只能访问其自身的数据

    (5)HTML5 使用 JavaScript 来存储和访问数据

    2.localStorage 方法:

    (1)localStorage 方法存储的数据没有时间限制。第二天、第二周或下一年之后,数据依然可用

    (2)如何创建和访问 localStorage:

    		<script type="text/javascript">
    			localStorage.lastname="Smith";
    			document.write(localStorage.lastname);
    		</script>
    

    (3)对用户访问页面的次数进行计数的例子:

    		<script type="text/javascript">
    			if (localStorage.pagecount)
    			 {
    				  localStorage.pagecount=Number(localStorage.pagecount) +1;
    			  }
    			else
    			{
    			  localStorage.pagecount=1;
    			}
    			document.write("Visits "+ localStorage.pagecount + " time(s).");
    		</script>
    

    3.sessionStorage 方法:

    (1)sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除

    (2)如何创建并访问一个 sessionStorage:

    		<script type="text/javascript">
    			sessionStorage.lastname="Smith";
    			document.write(sessionStorage.lastname);
    		</script>
    

    (3)对用户在当前 session 中访问页面的次数进行计数的例子:

    		<script type="text/javascript">
    		if (sessionStorage.pagecount)
    		 {
    			  sessionStorage.pagecount=Number(sessionStorage.pagecount) +1;
    		  }
    		else
    		  {
    			 sessionStorage.pagecount=1;
    		  }
    		document.write("Visits "+sessionStorage.pagecount+" time(s) this session.");
    		</script>
    

    十一.HTML 5 应用程序缓存:

    1.什么是应用程序缓存:

    (1)HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问

    (2)应用程序缓存为应用带来三个优势:

    a.离线浏览 - 用户可在应用离线时使用它们

    b.速度 - 已缓存资源加载得更快

    c.减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。

    (3)使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本

    2.HTML5 Cache Manifest 实例:

    带有 cache manifest 的 HTML 文档(供离线浏览)的示例:

    		<!DOCTYPE HTML>
    		<html manifest="demo.appcache">
    		<body>
    		The content of the document......
    		</body>
    		</html>
    

    3.Cache Manifest 基础:

    (1)如需启用应用程序缓存,在文档的 标签中包含 manifest 属性

    (2)manifest 文件的建议的文件扩展名是:".appcache"

    (3)manifest 文件需要配置正确的 MIME-type,即 “text/cache-manifest”。必须在 web 服务器上进行配置

    4.Manifest 文件:

    (1)manifest 文件是简单的文本文件,它告知浏览器被缓存的内容(以及不缓存的内容)

    (2)manifest 文件可分为三个部分:

    a.CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存

    b.NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存

    c.FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

    (3)CACHE MANIFEST:

    第一行,CACHE MANIFEST,是必需的:

    			CACHE MANIFEST
    			/theme.css
    			/logo.gif
    			/main.js
    

    manifest 文件列出了三个资源:一个 CSS 文件,一个 GIF 图像,以及一个 JavaScript 文件。当 manifest 文件加载后,浏览器会从网站的根目录下载这三个文件。然后,无论用户何时与因特网断开连接,这些资源依然是可用的

    (4)NETWORK:

    NETWORK 小节规定文件 “login.asp” 永远不会被缓存,且离线时是不可用的:

    			NETWORK:
    			login.asp
    

    可以使用星号来指示所有其他资源/文件都需要因特网连接:

    			NETWORK:
    			*
    

    (5)FALLBACK:

    FALLBACK 小节规定如果无法建立因特网连接,则用 “offline.html” 替代 /html5/ 目录中的所有文件:

    			FALLBACK:
    			/html5/ /404.html
    

    第一个 URI 是资源,第二个是替补

    5.更新缓存:

    (1)一旦应用被缓存,它就会保持缓存直到发生下列情况:

    a.用户清空浏览器缓存

    b.manifest 文件被修改(参阅下面的提示)

    c.由程序来更新应用缓存

    (2)完整的 Manifest 文件:

    		CACHE MANIFEST
    		# 2012-02-21 v1.0.0
    		/theme.css
    		/logo.gif
    		/main.js
    
    		NETWORK:
    		login.asp
    
    		FALLBACK:
    		/html5/ /404.html
    

    (3)以 “#” 开头的是注释行,但也可满足其他用途。应用的缓存会在其 manifest 文件更改时被更新

    (4)如果您编辑了一幅图片,或者修改了一个 JavaScript 函数,这些改变都不会被重新缓存。更新注释行中的日期和版本号是一种使浏览器重新缓存文件的办法。

    6.关于应用程序缓存的注释:

    (1)一旦文件被缓存,则浏览器会继续展示已缓存的版本,即使您修改了服务器上的文件。为了确保浏览器更新缓存,您需要更新 manifest 文件

    (2)浏览器对缓存数据的容量限制可能不太一样

    十二.Web Workers:

    1.什么是 Web Worker:

    (1)web worker 是运行在后台的 JavaScript,不会影响页面的性能

    (2)当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成
    (3)web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行

    2.HTML5 Web Workers 实例:

    (1)检测 Web Worker 支持:

    在创建 web worker 之前,请检测用户的浏览器是否支持它:

    			if(typeof(Worker)!=="undefined")
    			{
    			// Yes! Web worker support!
    			 // Some code.....
    			}
    			else
    			{
    			 // Sorry! No Web Worker support..
    			}
    

    (2)创建 web worker 文件:

    在一个外部 JavaScript 中创建我们的 web worker

    我们创建了计数脚本。该脚本存储于 “demo_workers.js” 文件中:

    			var i=0;
    
    		function timedCount()
    		{
    			i=i+1;
    			postMessage(i);
    			setTimeout("timedCount()",500);
    		}
    		timedCount();
    

    (3)创建 Web Worker 对象:
    下面的代码检测是否存在 worker,如果不存在,- 它会创建一个新的 web worker 对象,然后运行 “demo_workers.js” 中的代码:

    			if(typeof(w)=="undefined")
    			 {
    				 w=new Worker("demo_workers.js");
    			  }
    

    然后我们就可以从 web worker 发生和接收消息了。向 web worker 添加一个 “onmessage” 事件监听器:

    			w.onmessage=function(event){
    				document.getElementById("result").innerHTML=event.data;
    			};
    

    (4)终止 Web Worker:

    当我们创建 web worker 对象后,它会继续监听消息(即使在外部脚本完成之后)直到其被终止为止。

    如需终止 web worker,并释放浏览器/计算机资源,请使用 terminate() 方法:

    			w.terminate();
    

    3.Web Workers 和 DOM:

    由于 web worker 位于外部文件中,它们无法访问下例 JavaScript 对象:

    window 对象、document 对象、parent 对象
    

    十三.服务器发送事件:

    1.Server-Sent 事件 - 单向消息传递:

    (1)Server-Sent 事件指的是网页自动获取来自服务器的更新

    (2)以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过服务器发送事件,更新能够自动到达。

    例子:Facebook/Twitter 更新、估价更新、新的博文、赛事结果等。

    (3)HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新

    2.接收 Server-Sent 事件通知:

    (1)EventSource 对象用于接收服务器发送事件通知:

    		var source=new EventSource("demo_sse.php");
    		source.onmessage=function(event)
    		{
    			document.getElementById("result").innerHTML+=event.data + "<br />";
    		};
    

    (2)例子解释:

    创建一个新的 EventSource 对象,然后规定发送更新的页面的 URL(本例中是 “demo_sse.php”)

    每接收到一次更新,就会发生 onmessage 事件

    当 onmessage 事件发生时,把已接收的数据推入 id 为 “result” 的元素中

    3.检测 Server-Sent 事件支持:

    检测服务器发送事件的浏览器支持情况:

    		if(typeof(EventSource)!=="undefined")
    		{
    		 // Yes! Server-sent events support!
    		// Some code.....
    		}
    		else
    		{
    		// Sorry! No server-sent events support..
    		}
    

    4.服务器端代码实例:

    (1)为了让上面的例子可以运行,您还需要能够发送数据更新的服务器(比如 PHP 和 ASP)

    (2)服务器端事件流的语法是非常简单的。把 “Content-Type” 报头设置为 “text/event-stream”

    5.EventSource 对象:

    	事件				描述
    
    	onopen			当通往服务器的连接被打开
    
    	onmessage		当接收到消息
    
    	onerror			当错误发生
    

    十四.Input 类型:

    1.新的 Input 类型:

    email、url、number、range、Date pickers (date, month, week, time, datetime, datetime-local)、search、color

    2.浏览器支持:

    	nput type	IE		Firefox		Opera		Chrome		Safari
    
    	email		No		4.0			9.0			10.0		No
    
    	url			No		4.0			9.0			10.0		No
    
    	number		No		No			9.0			7.0			No
    
    	range		No		No			9.0			4.0			4.0
    
    Date pickers	No		No			9.0			10.0		No
    
    	search		No		4.0			11.0		10.0		No
    
    	color		No		No			11.0		No			No
    

    3.Input 类型 - email:

    (1)email 类型用于应该包含 e-mail 地址的输入域,在提交表单时,会自动验证 email 域的值

    (2)代码示例:

    		E-mail: <input type="email" name="user_email" />
    

    4.Input 类型 - url:

    (1)url 类型用于应该包含 URL 地址的输入域。在提交表单时,会自动验证 url 域的值

    (2)代码示例:

    		Homepage: <input type="url" name="user_url" />
    

    5.Input 类型 - number:

    (1)number 类型用于应该包含数值的输入域。您还能够设定对所接受的数字的限定

    (2)示例代码:

    		Points: <input type="number" name="points" min="1" max="10" />
    

    (3)下面的属性来规定对数字类型的限定:

    		属性			值			描述
    
    		max			number		规定允许的最大值
    
    		min			number		规定允许的最小值
    
    		step		number		规定合法的数字间隔(如果 step="3",则合法的数是 -3,0,3,6 等)
    
    		value		number		规定默认值
    

    6.Input 类型 - range:

    (1)range 类型用于应该包含一定范围内数字值的输入域,range 类型显示为滑动条,您还能够设定对所接受的数字的限定

    (2)代码示例:

    		<input type="range" name="points" min="1" max="10" />
    

    7.Input 类型 - Date Pickers(日期选择器):

    (1)HTML5 拥有多个可供选取日期和时间的新输入类型:

    date - 选取日、月、年

    month - 选取月、年

    week - 选取周和年

    time - 选取时间(小时和分钟)

    datetime - 选取时间、日、月、年(UTC 时间)

    datetime-local - 选取时间、日、月、年(本地时间)

    (2)代码示例:

    		Date: <input type="date" name="user_date" />
    

    8.Input 类型 - search:

    (1)search 类型用于搜索域,比如站点搜索或 Google 搜索。

    (2)search 域显示为常规的文本域

    十五.HTML5 表单元素:

    1.HTML5 的新的表单元素:

    datalist、keygen、output

    2.浏览器支持:

    	Input type	IE	Firefox		Opera	Chrome	Safari
    
    	datalist	No	No			9.5		No		No
    
    	keygen		No	No			10.5	3.0		No
    
    	output		No	No			9.5		No		No
    

    3.datalist 元素:

    (1)datalist 元素规定输入域的选项列表,列表是通过 datalist 内的 option 元素创建的;

    (2)如需把 datalist 绑定到输入域,请用输入域的 list 属性引用 datalist 的 id:

    		Webpage: <input type="url" list="url_list" name="link" />
    		<datalist id="url_list">
    		<option label="W3School" value="http://www.W3School.com.cn" />
    		<option label="Google" value="http://www.google.com" />
    		<option label="Microsoft" value="http://www.microsoft.com" />
    		</datalist>
    

    (3)option 元素永远都要设置 value 属性

    4.keygen 元素:

    (1)keygen 元素的作用是提供一种验证用户的可靠方法

    (2)keygen 元素是密钥对生成器(key-pair generator)。当提交表单时,会生成两个键,一个是私钥,一个公钥

    私钥(private key)存储于客户端,公钥(public key)则被发送到服务器。公钥可用于之后验证用户的客户端证书(client certificate)。

    (3)目前,浏览器对此元素的糟糕的支持度不足以使其成为一种有用的安全标准。

    (4)代码示例:

    		<form action="demo_form.asp" method="get">
    		Username: <input type="text" name="usr_name" />
    		Encryption: <keygen name="security" />
    		<input type="submit" />
    		</form>
    

    5.output 元素:

    (1)output 元素用于不同类型的输出,比如计算或脚本输出:

    (2)代码示例:

    		<output id="result" onforminput="resCalc()"></output>
    

    十六.HTML5 表单属性:

    1.HTML5 的新的表单属性:

    (1)新的 form 属性:

    autocomplete、novalidate

    (2)新的 input 属性:

    autocomplete、autofocus、form、form overrides (formaction, formenctype, formmethod, formnovalidate, formtarget)、height 和 width、list、min, max 和 step、multiple、pattern (regexp)、placeholder、required

    2.浏览器支持:

    	Input type			IE		Firefox		Opera		Chrome		Safari
    
    	autocomplete		8.0		3.5			9.5			3.0			4.0
    
    	autofocus			No		No			10.0		3.0			4.0
    
    	form				No		No			9.5			No			No
    
    	form overrides		No		No			10.5		No			No
    
    	height and width		8.0		3.5			9.5			3.0			4.0
    
    	list				No		No			9.5			No			No
    
    	min, max and step	No		No			9.5			3.0			No
    
    	multiple			No		3.5			No			3.0			4.0
    
    	novalidate			No		No			No			No			No
    
    	pattern				No		No			9.5			3.0			No
    
    	placeholder			No		No			No			3.0			3.0
    
    	required			No		No			9.5			3.0			No
    

    3.autocomplete 属性:

    (1)autocomplete 属性规定 form 或 input 域应该拥有自动完成功能

    (2)autocomplete 适用于 标签,以及以下类型的 标签:text, search, url, telephone, email, password, datepickers, range 以及 color

    (3)当用户在自动完成域中开始输入时,浏览器应该在该域中显示填写的选项:

    		<form action="demo_form.asp" method="get" autocomplete="on">
    		First name: <input type="text" name="fname" /><br />
    		Last name: <input type="text" name="lname" /><br />
    		E-mail: <input type="email" name="email" autocomplete="off" /><br />
    		<input type="submit" />
    		</form>
    

    4.autofocus 属性:

    (1)autofocus 属性规定在页面加载时,域自动地获得焦点。

    (2)autofocus 属性适用于所有 标签的类型

    (3)代码示例:

    		User name: <input type="text" name="user_name"  autofocus="autofocus" />
    

    5.form 属性:

    (1)form 属性规定输入域所属的一个或多个表单

    (2)form 属性适用于所有 标签的类型

    (3)form 属性必须引用所属表单的 id

    (4)代码示例:

    		<form action="demo_form.asp" method="get" id="user_form">
    		First name:<input type="text" name="fname" />
    		<input type="submit" />
    		</form>
    		Last name: <input type="text" name="lname" form="user_form" />
    

    6.表单重写属性:

    (1)表单重写属性(form override attributes)允许您重写 form 元素的某些属性设定

    (2)表单重写属性有:

    formaction - 重写表单的 action 属性

    formenctype - 重写表单的 enctype 属性

    formmethod - 重写表单的 method 属性

    formnovalidate - 重写表单的 novalidate 属性

    formtarget - 重写表单的 target 属性

    (3)表单重写属性适用于以下类型的 标签:submit 和 image

    (4)代码示例:

    		<form action="demo_form.asp" method="get" id="user_form">
    		E-mail: <input type="email" name="userid" /><br />
    		<input type="submit" value="Submit" />
    		<br />
    		<input type="submit" formaction="demo_admin.asp" value="Submit as admin" />
    		<br />
    		<input type="submit" formnovalidate="true" value="Submit without validation" />
    		<br />
    		</form>
    

    7.height 和 width 属性:

    (1)height 和 width 属性规定用于 image 类型的 input 标签的图像高度和宽度

    (2)height 和 width 属性只适用于 image 类型的 标签

    (3)代码示例:

    		<input type="image" src="img_submit.gif" width="99" height="99" />
    

    8.list 属性:

    (1)list 属性规定输入域的 datalist。datalist 是输入域的选项列表

    (2)list 属性适用于以下类型的 标签:text, search, url, telephone, email, date pickers, number, range 以及 color。

    (3)代码示例:

    		Webpage: <input type="url" list="url_list" name="link" />
    		<datalist id="url_list">
    		<option label="W3Schools" value="http://www.w3school.com.cn" />
    		<option label="Google" value="http://www.google.com" />
    		<option label="Microsoft" value="http://www.microsoft.com" />
    		</datalist>
    

    9.min、max 和 step 属性:

    (1)min、max 和 step 属性用于为包含数字或日期的 input 类型规定限定(约束)

    (2)max 属性规定输入域所允许的最大值。

    min 属性规定输入域所允许的最小值。

    step 属性为输入域规定合法的数字间隔(如果 step=“3”,则合法的数是 -3,0,3,6 等)

    (3)min、max 和 step 属性适用于以下类型的 标签:date pickers、number 以及 range

    (4)代码实例:

    		Points: <input type="number" name="points" min="0" max="10" step="3" />
    

    10.multiple 属性:

    (1)multiple 属性规定输入域中可选择多个值

    (2)multiple 属性适用于以下类型的 标签:email 和 file

    (3)代码实例:

    		Select images: <input type="file" name="img" multiple="multiple" />
    

    11.novalidate 属性:

    (1)novalidate 属性规定在提交表单时不应该验证 form 或 input 域

    (2)novalidate 属性适用于 以及以下类型的 标签:text, search, url, telephone, email, password, date pickers, range 以及 color.

    (3)代码示例:

    		<form action="demo_form.asp" method="get" novalidate="true">
    		E-mail: <input type="email" name="user_email" />
    		<input type="submit" />
    		</form>
    

    12.pattern 属性:

    (1)pattern 属性规定用于验证 input 域的模式(pattern)

    (2)模式(pattern) 是正则表达式

    (3)pattern 属性适用于以下类型的 标签:text, search, url, telephone, email 以及 password

    (4)下面的例子显示了一个只能包含三个字母的文本域(不含数字及特殊字符):

    		Country code: <input type="text" name="country_code"
    		pattern="[A-z]{3}" title="Three letter country code" />
    

    13.placeholder 属性:

    (1)placeholder 属性提供一种提示(hint),描述输入域所期待的值

    (2)placeholder 属性适用于以下类型的 标签:text, search, url, telephone, email 以及 password。

    (3)提示(hint)会在输入域为空时显示出现,会在输入域获得焦点时消失:

    		<input type="search" name="user_search"  placeholder="Search W3School" />
    

    14.required 属性:

    (1)required 属性规定必须在提交之前填写输入域(不能为空)

    (2)required 属性适用于以下类型的 标签:text, search, url, telephone, email, password, date pickers, number, checkbox, radio 以及 file

    (3)代码示例:

    		Name: <input type="text" name="usr_name" required="required" />
    
    展开全文
  • HTML5不是什么新鲜事。自初始版本(2008 年 1 月)以来,我们一直在使用它的几个功能。我再次仔细查看了 HTML5 功能列表。看看我发现了什么?到目前为止,我还没有真正使用过很多! 在本文中,我列出了 10 个这样的...

    博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

    HTML5不是什么新鲜事。自初始版本(2008 年 1 月)以来,我们一直在使用它的几个功能。我再次仔细查看了 HTML5 功能列表。看看我发现了什么?到目前为止,我还没有真正使用过很多!

    在本文中,我列出了 10 个这样的HTML5功能,这些功能过去我用得不多,但现在发现它们很有用。我还创建了一个工作示例流程并托管在GitHub. 希望你也觉得它有用。让我们开始了解有关它们中的每一个的解释、代码和快速提示。

    https://wanghao221.github.io/html-tips-tricks/

    展开全文
  • HTML5新特性浅谈

    万次阅读 多人点赞 2016-10-17 21:25:58
    2014年10月29日,W3C宣布,经过接近8年的艰苦努力,HTML5标准规范终于制定完成。HTML5将会取代1999年制定的HTML 4.01、XHTML 1.0标准,以期能在互联网应用迅速发展的时候...这些年为了兼容IE6放弃了很多HTML5新特性

    这里写图片描述

    转载请注明出处:

    http://blog.csdn.net/gane_cheng/article/details/52819118

    http://www.ganecheng.tech/blog/52819118.html (浏览效果更好)

    2014年10月29日,W3C宣布,经过接近8年的艰苦努力,HTML5标准规范终于制定完成。

    HTML5将会取代1999年制定的HTML 4.01、XHTML 1.0标准,以期能在互联网应用迅速发展的时候,使网络标准达到符合当代的网络需求,为桌面和移动平台带来无缝衔接的丰富内容。

    作为2010年入坑IT的程序员来说,可以说一步一步见证着HTML5的发展。这些年为了兼容IE6放弃了很多HTML5的新特性。但是今时不同以往,移动设备的流行,天然支持HTML5,以及桌面端IE最终被用户和微软唾弃,更多支持HTML5浏览器的受欢迎,我要重新研究一下HTML5带来的这些新特性。

    HTML5 的新特性

    ① 语义特性(Semantic)

    HTML5赋予网页更好的意义和结构。

    ② 本地存储特性(OFFLINE & STORAGE)

    基于HTML5开发的网页APP拥有更短的启动时间,更快的联网速度,这些全得益于HTML5 APP Cache,以及本地存储功能。

    ③ 设备访问特性 (DEVICE ACCESS)

    从Geolocation功能的API文档公开以来,HTML5为网页应用开发者们提供了更多功能上的优化选择,带来了更多体验功能的优势。HTML5提供了前所未有的数据与应用接入开放接口。使外部应用可以直接与浏览器内部的数据直接相连,例如视频影音可直接与microphones及摄像头相联。

    ④ 连接特性(CONNECTIVITY)

    更有效的连接工作效率,使得基于页面的实时聊天,更快速的网页游戏体验,更优化的在线交流得到了实现。HTML5拥有更有效的服务器推送技术,Server-Sent Event和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据“推送”到客户端的功能。

    ⑤ 网页多媒体特性(MULTIMEDIA)

    支持网页端的Audio、Video等多媒体功能, 与网站自带的APPS,摄像头,影音功能相得益彰。

    ⑥ 三维、图形及特效特性(3D, Graphics & Effects)

    基于SVG、Canvas、WebGL及CSS3的3D功能,用户会惊叹于在浏览器中,所呈现的惊人视觉效果。

    ⑦ 性能与集成特性(Performance & Integration)

    没有用户会永远等待你的Loading——HTML5会通过XMLHttpRequest2等技术,解决以前的跨域等问题,帮助您的Web应用和网站在多样化的环境中更快速的工作。


    下面分别对这七个新特性进行研究。

    ① 语义特性(Semantic)

    这里写图片描述

    HTML5增加了新的内容标签,这些标签带有一定的语义,使搜索引擎爬取你的网站信息更高效。

    这里写图片描述

    HTML4中的内容标签级别相同,无法区分各部分内容。而HTML5中的内容标签互相独立,级别不同,搜索引擎以及统计软件等均可快速识别各部分内容。

    这些标签在新闻类网站,博客类网站很有用。

    最大的问题就是当使用这些新的语义元素时,那些不支持的浏览器如何处理这些元素。

    见过的最多的解决方法是这样的。

    <section class="section">
    
        <!-- content --> 
    
    </section>
    .section 
    {
         color: blue;
    }

    如果还想了解更多语义标签兼容性问题,可以参考这篇文章http://html5.group.iteye.com/group/wiki/3293-html5

    ② 本地存储特性(OFFLINE & STORAGE)

    这里写图片描述

    HTML5提供了网页存储的API,方便Web应用的离线使用。除此之外,新的API相对于cookie也有着高安全性,高效率,更大空间等优点。

    先看W3C对离线存储的介绍。

    Web Apps can start faster and work even if there is no internet connection, thanks to the HTML5 App Cache, as well as the Local Storage, Indexed DB, and the File API specifications.

    HTML5离线存储包含 应用程序缓存本地存储索引数据库文件接口

    下面依次展开介绍。

    (1)应用程序缓存(Application Cache)

    这里写图片描述

    使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本。

    HTML5引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。

    应用程序缓存为应用带来三个优势:

    • 离线浏览 – 用户可在应用离线时使用它们
    • 速度 – 已缓存资源加载得更快
    • 减少服务器负载 – 浏览器将只从服务器下载更新过或更改过的资源。

    甭废话,先来感受一下Application Cache的魅力。Shut up,show me the demo!

    Demo链接:http://www.ganecheng.tech/welcome_offline.html

    1.打开这个网页,第一次等待加载完成之后,页面和普通的网页没有区别。

    2.点击刷新按钮,或者强制刷新按钮,看一下第二次打开的速度。有没有快到爆。(速度

    3.现在我要求你拔掉网线,断开WiFi,再次点击刷新按钮,或者强制刷新按钮,看一下第三次打开的速度。有没有快到爆。注意,现在并没有联网,和服务器失去连接,依然秒开网页,还能正常操作网页。(离线浏览,减少服务器负载

    看完了效果,看一下App Cache的原理。

    这里写图片描述

    当我们第一次正确配置cache manifest后,浏览器会将清单文件中的资源缓存下来。当我们再次访问该应用时,浏览器会直接返回缓存中的资源,然后检查manifest文件是否有变动,如果有变动就会把相应的变动更新下来,同时改变浏览器里面的app cache。

    使用方法

    页面声明使用App Cache

     <!DOCTYPE HTML> 
     <html manifest="index.manifest"> 

    清单文件中写明资源。

    CACHE MANIFEST
    theme.css 
    logo.gif 
    main.js
    
    NETWORK:
    login.asp
    
    FALLBACK:
    /html5/ /404.html

    manifest 文件可分为三个部分:

    CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
    NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
    FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

    CACHE MANIFEST,是必需的
    NETWORK 规定文件 “login.asp” 永远不会被缓存,且离线时是不可用的
    FALLBACK 规定如果无法建立因特网连接,则用 “404.html” 替代 /html5/ 目录中的所有文件

    一旦应用被缓存,它就会保持缓存直到发生下列情况:

    • 用户清空浏览器缓存 ,用户怎么做,页面左右不了,说了等于没说。
    • manifest 文件被修改,请注意:更新清单中列出的某个文件并不意味着浏览器会重新缓存该资源。清单文件本身必须进行更改,一般是加一个注释,注释的内容是日期,想更新了,改一下日期。
    • 由程序来更新应用缓存,这个稍微靠谱一点。

    需要注意的是,更新后的资源需要下次打开页面才能生效,本次打开的页面在更新资源之前就已经从缓存中拿到资源并加载完毕了。

    由程序来更新,需要依赖manifest文件被修改这一条,因为调用的是浏览器提供的接口,检测 window.applicationCache.status 的值,如果是 UPDATEREADY,说明浏览器比较manifest文件完毕,可以更新缓存了。window.applicationCache.swapCache()。更新完了,不会立即生效,window.location.reload();重新加载一下页面。

    缓存有这么多状态。

    var appCache = window.applicationCache; 
    switch (appCache.status) 
    { 
        case appCache.UNCACHED: // UNCACHED == 0 
            return 'UNCACHED'; 
            break; 
        case appCache.IDLE: // IDLE == 1 
            return 'IDLE'; 
            break; 
        case appCache.CHECKING: // CHECKING == 2 
            return 'CHECKING'; 
            break; 
        case appCache.DOWNLOADING: // DOWNLOADING == 3 
            return 'DOWNLOADING'; 
            break; 
        case appCache.UPDATEREADY: // UPDATEREADY == 4 
            return 'UPDATEREADY'; 
            break; 
        case appCache.OBSOLETE: // OBSOLETE == 5 
            return 'OBSOLETE'; 
            break; 
        default: 
            return 'UKNOWN CACHE STATUS'; 
            break; 
    }; 

    程序更新缓存的方法。

    // Check if a new cache is available on page load. 
    window.addEventListener('load', function(e) 
    { 
        window.applicationCache.addEventListener('updateready', function(e) 
        { 
            if (window.applicationCache.status == window.applicationCache.UPDATEREADY) 
            { 
                // Browser downloaded a new app cache. 
                // Swap it in and reload the page to get the new hotness. 
                window.applicationCache.swapCache(); 
                if (confirm('A new version of this site is available. Load it?')) 
                { 
                    window.location.reload(); 
                } 
            } 
            else 
            { 
                // Manifest didn't changed. Nothing new to server. 
            }                                                                                       
        }, false); 
    }, false); 

    更多更新缓存的方法,可以参考这篇文章:http://www.jb51.net/html5/67850.html

    总的来说,App Cache的三个优点非常明显。但是有几个坑,却会导致没人愿意使用这个新特性。

    1.使用了App Cache的页面在清单文件更新之后去更新页面资源,但是只在下次打开页面才能生效,这意味着,我们需要使用代码判断是不是最新版本,不是的话,刷新一次页面。这种体验很不好。

    2.使用了App Cache的页面也会被缓存,这对于需要动态更新的页面来说,几乎是个噩梦。用户访问到的页面不是最新的,会导致非常多的问题。

    3.App cache与browser cache混合在一起会使更新机制变得更加复杂,主要有以下几个因素:
    1) App cache在各浏览器平台实现上存在差异;
    2) 各浏览器又提供了不同的页面刷新机制;
    3) app cache还与传统的browser cache有着千丝万缕的联系;对于它俩如何协同工作,HTML5的相关规范没有对app cache的细节给出非常明确的规定; 浏览器官方文档有没有给出非常明确的说明。
    4) browser cache的更新机制本身就已经很复杂。
    5) 如果manifest文件本身就有缓存时间,或设置为永远都可用,那你的网页永远都不会被更新了。

    App Cache更多的坑,可以参考这篇文章:http://dreclo.blog.163.com/blog/static/528789512014111675023409/ , 然后再决定要不要使用这一新特性。

    从惊叹于App Cache的强大,到填坑,W3C花了这么长时间,就弄出来这么个东西,真是令人失望。学会使用App Cache只用了不到一小时,填坑填了一下午。每个页面都要有manifest,每个页面都要加代码去判断去更新缓存,我可以骂人吗。


    (2)本地存储(Local Storage)

    这里写图片描述

    本地存储发展历史.

    这里写图片描述

    最早的Cookies自然是大家都知道,问题主要就是太小,大概也就4KB的样子,而且IE6只支持每个域名20个cookies,太少了。优势就是大家都支持,而且支持得还蛮好。很早以前那些禁用cookies的用户也都慢慢的不存在了,就好像以前禁用javascript的用户不存在了一样。

    userData是IE的东西,垃圾。现在用的最多的是Flash吧,空间是Cookie的25倍,基本够用。再之后Google推出了Gears,虽然没有限制,但不爽的地方就是要装额外的插件(没具体研究过)。到了HTML5把这些都统一了,官方建议是每个网站5MB,非常大了,就存些字符串,足够了。比较诡异的是居然所有支持的浏览器目前都采用的5MB,尽管有一些浏览器可以让用户设置,但对于网页制作者来说,目前的形势就5MB来考虑是比较妥当的。

    首先自然是检测浏览器是否支持本地存储。在HTML5中,本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。

    if(window.localStorage)
    {
         alert('This browser supports localStorage');
    }
    else
    {
         alert('This browser does NOT support localStorage');
    }

    存储数据的方法就是直接给window.localStorage添加一个属性,例如:window.localStorage.a 或者 window.localStorage[“a”]。它的读取、写、删除操作方法很简单,是以键值对的方式存在的,如下:

    localStorage.a = 3;//设置a为"3"
    localStorage["a"] = "sfsf";//设置a为"sfsf",覆盖上面的值
    localStorage.setItem("b","isaac");//设置b为"isaac"
    var a1 = localStorage["a"];//获取a的值
    var a2 = localStorage.a;//获取a的值
    var b = localStorage.getItem("b");//获取b的值
    localStorage.removeItem("c");//清除c的值

    这里最推荐使用的自然是getItem()和setItem(),清除键值对使用removeItem()。如果希望一次性清除所有的键值对,可以使用clear()。另外,HTML5还提供了一个key()方法,可以在不知道有哪些键值的时候使用,如下:

    var storage = window.localStorage;
    function showStorage()
    {
         for(var i=0;i<storage.length;i++)
         {
              //key(i)获得相应的键,再用getItem()方法获得对应的值
              document.write(storage.key(i)+ " : " + storage.getItem(storage.key(i)) + "<br>");
         }
    }

    写一个最简单的,利用本地存储的计数器:

        var storage = window.localStorage;
        if (!storage.getItem("pageLoadCount")) 
        {
            storage.setItem("pageLoadCount",0);
        }
        storage.pageLoadCount = parseInt(storage.getItem("pageLoadCount")) + 1;//必须格式转换
        document.getElementById("count").innerHTML = storage.pageLoadCount;
        showStorage();

    不断刷新就能看到数字在一点点上涨,如下图所示:

    这里写图片描述

    需要注意的是,HTML5本地存储只能存字符串,任何格式存储的时候都会被自动转为字符串,所以读取的时候,需要自己进行类型的转换。这也就是上一段代码中parseInt必须要使用的原因。

    想要对localStorage了解更多请参考这篇文章:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html

    (3)索引数据库(Indexed DB)

    这里写图片描述

    从本质上说,IndexedDB允许用户在浏览器中保存大量的数据。任何需要发送大量数据的应用都可以得益于这个特性,可以把数据存储在用户的浏览器端。当前这只是IndexedDB的其中一项功能,IndexedDB也提供了强大的基于索引的搜索api功能以获得用户所需要的数据。

    用户可能会问:IndexedDB是和其他以前的存储机制(如cookie,session)有什么不同?

    Cookies是最常用的浏览器端保存数据的机制,但其保存数据的大小有限制并且有隐私问题。Cookies并且会在每个请求中来回发送数据,完全没办法发挥客户端数据存储的优势。

    再来看下Local Storage本地存储机制的特点。Local Storage在HTML 5中有不错的支持,但就总的存储量而言依然是有所限制的。Local Storage并不提供真正的“检索API”,本地存储的数据只是通过键值对去访问。Local Storage对于一些特定的需要存储数据的场景是很适合的,例如,用户的喜好习惯,而IndexedDB则更适合存储如广告等数据(它更象一个真正的数据库)。

    一般来说,有两种不同类型的数据库:关系型和文档型(也称为NoSQL或对象)。关系数据库如SQL Server,MySQL,Oracle的数据存储在表中。文档数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存储。IndexedDB是一个文档数据库,它在完全内置于浏览器中的一个沙盒环境中(强制依照(浏览器)同源策略)。

    对数据库的每次操作,描述为通过一个请求打开数据库,访问一个object store,再继续。

    打开数据库的请求生命周期

    这里写图片描述

    IndexedDB是否适合我的应用程序?

    现在最关键的问题:“IndexedDB是否适合我的应用程序?“像往常一样,答案是肯定的:“视情况而定。“首先当你试图在客户端保存数据时,你会考虑HTML5本地存储。本地存储得到广泛浏览器的支持,有非常易于使用的API。简单有其优势,但其劣势是无法支持复杂的搜索策略,存储大量的数据,并提供事务支持。

    IndexedDB是一个数据库。所以,当你想为客户端做出决定,考虑你如何在服务端选择一个持久化介质的数据库。你可能会问自己一些问题来帮助决定客户端数据库是否适合您的应用程序,包括:

    • 你的用户通过浏览器访问您的应用程序,(浏览器)支持IndexedDB API吗 ?
    • 你需要存储大量的数据在客户端?
    • 你需要在一个大型的数据集合中快速定位单个数据点?
    • 你的架构在客户端需要事务支持吗?

      如果你对其中的任何问题回答了“是的”,很有可能,IndexedDB是你的应用程序的一个很好的候选。

    IndexedDB用法

    现在,你已经有机会熟悉了一些的整体概念,下一步是开始实现基于IndexedDB的应用程序。第一个步骤需要统一IndexedDB在不同浏览器的实现。您可以很容易地添加各种厂商特性的选项的检查,同时在window对象上把它们设置为官方对象相同的名称。下面的清单展示了window.indexedDB,window.IDBTransaction,window.IDBKeyRange的最终结果是如何都被更新,它们被设置为相应的浏览器的特定实现。

            window.indexedDB = window.indexedDB ||
                               window.mozIndexedDB ||
                               window.webkitIndexedDB ||
                               window.msIndexedDB;
    
            window.IDBTransaction = window.IDBTransaction ||
                               window.webkitIDBTransaction ||
                               window.msIDBTransaction;
    
            window.IDBKeyRange = window.IDBKeyRange ||
                               window.webkitIDBKeyRange ||
                               window.msIDBKeyRange;

    现在,每个数据库相关的全局对象持有正确的版本,应用程序可以准备使用IndexedDB开始工作。

    打开数据库

    // 打开我们的数据库,数据库名称,版本号
    var request = indexedDB.open("MyTestDatabase", 3);

    indexedDB的三个事件

    //数据库打开成功执行
    request.onsuccess = function (event) 
    {
          // Better use "this" than "req" to get the result to avoid problems with
          // garbage collection.
          // db = request.result;
          db = this.result;
          console.debug("initDb DONE");
    };
    //数据库打开失败执行
    request.onerror = function (event) 
    {
          console.error("initDb:", evt.target.errorCode);
    };
    //在数据库第一次被打开时或者当指定的版本号高于当前被持久化的数据库的版本号时,触发此事件,可以在这个地方创建对象存储空间结构,更新结构,加索引等.
    request.onupgradeneeded = function (event) 
    {
          console.debug("initDb.onupgradeneeded");
          var store = event.currentTarget.result.createObjectStore(
            DB_STORE_NAME, { keyPath: 'id', autoIncrement: true });
    };

    添加数据或更新数据

    // 我们的客户数据看起来像这样。
    const customerData = [
      { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
      { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
    ];
    
    var transaction = db.transaction(["customers"], "readwrite");
    
    // 当所有的数据都被增加到数据库时执行一些操作
    transaction.oncomplete = function(event) {
      alert("All done!");
    };
    
    transaction.onerror = function(event) {
      // 不要忘记进行错误处理!
    };
    
    var objectStore = transaction.objectStore("customers");
    for (var i in customerData) 
    {
      var request = objectStore.add(customerData[i]);
      request.onsuccess = function(event) 
      {
        // event.target.result == customerData[i].ssn
      };
    }

    删除数据

    var request = db.transaction(["customers"], "readwrite")
                    .objectStore("customers")
                    .delete("444-44-4444");
    request.onsuccess = function(event) {
      // 删除数据成功!
    };

    获取数据

    var transaction = db.transaction(["customers"]);
    var objectStore = transaction.objectStore("customers");
    var request = objectStore.get("444-44-4444");
    request.onerror = function(event) 
    {
      // 错误处理!
    };
    request.onsuccess = function(event) 
    {
      // 对 request.result 做些操作!
      alert("Name for SSN 444-44-4444 is " + request.result.name);
    };

    对于一个“简单”的提取这里的代码有点多了。下面看我们怎么把它再缩短一点,假设你在数据库的级别上来进行的错误处理:

    db.transaction("customers").objectStore("customers").get("444-44-4444").onsuccess = function(event) 
    {
      alert("Name for SSN 444-44-4444 is " + event.target.result.name);
    };

    使用游标获取数据

    使用 get() 要求你知道你想要检索哪一个键。如果你想要遍历对象存储空间中的所有值,那么你可以使用游标。看起来会像下面这样:

    var customers = [];
    
    var objectStore = db.transaction("customers").objectStore("customers");
    
    objectStore.openCursor().onsuccess = function(event) 
    {
      var cursor = event.target.result;
      if (cursor) 
      {
        customers.push(cursor.value);
        cursor.continue();
      }
      else 
      {
        alert("Got all customers: " + customers);
      }
    };

    这里有一个封装好的完整的例子,简化了这些操作。

    <script type="text/javascript">
    
            window.indexedDB = window.indexedDB ||
                               window.mozIndexedDB ||
                               window.webkitIndexedDB ||
                               window.msIndexedDB;
    
            window.IDBTransaction = window.IDBTransaction ||
                               window.webkitIDBTransaction ||
                               window.msIDBTransaction;
    
            window.IDBKeyRange = window.IDBKeyRange ||
                               window.webkitIDBKeyRange ||
                               window.msIDBKeyRange;
    
            (function(window){
    
                'use strict';
    
                var db = {
    
                    version: 1, // important: only use whole numbers!
    
                    objectStoreName: 'tasks',
    
                    instance: {},
    
                    upgrade: function (e) {
    
                        var
                            _db = e.target.result,
                            names = _db.objectStoreNames,
                            name = db.objectStoreName;
    
                        if (!names.contains(name)) {
    
                            _db.createObjectStore(
                                name,
                                {
                                    keyPath: 'id',
                                    autoIncrement: true
                                });
                        }
                    },
    
                    errorHandler: function (error) {
                        window.alert('error: ' + error.target.code);
                        debugger;
                    },
    
                    open: function (callback) {
    
                        var request = window.indexedDB.open(
                            db.objectStoreName, db.version);
    
                        request.onerror = db.errorHandler;
    
                        request.onupgradeneeded = db.upgrade;
    
                        request.onsuccess = function (e) {
    
                            db.instance = request.result;
    
                            db.instance.onerror =
                                db.errorHandler;
    
                            callback();
                        };
                    },
    
                    getObjectStore: function (mode) {
    
                        var txn, store;
    
                        mode = mode || 'readonly';
    
                        txn = db.instance.transaction(
                            [db.objectStoreName], mode);
    
                        store = txn.objectStore(
                            db.objectStoreName);
    
                        return store;
                    },
    
                    save: function (data, callback) {
    
                        db.open(function () {
    
                            var store, request,
                                mode = 'readwrite';
    
                            store = db.getObjectStore(mode),
    
                            request = data.id ?
                                store.put(data) :
                                store.add(data);
    
                            request.onsuccess = callback;
                        });
                    },
    
                    getAll: function (callback) {
    
                        db.open(function () {
    
                            var
                                store = db.getObjectStore(),
                                cursor = store.openCursor(),
                                data = [];
    
                            cursor.onsuccess = function (e) {
    
                                var result = e.target.result;
    
                                if (result &&
                                    result !== null) {
    
                                    data.push(result.value);
                                    result.continue();
    
                                } else {
    
                                    callback(data);
                                }
                            };
    
                        });
                    },
    
                    get: function (id, callback) {
    
                        id = parseInt(id);
    
                        db.open(function () {
    
                            var
                                store = db.getObjectStore(),
                                request = store.get(id);
    
                            request.onsuccess = function (e){
                                callback(e.target.result);
                            };
                        });
                    },
    
                    'delete': function (id, callback) {
    
                        id = parseInt(id);
    
                        db.open(function () {
    
                            var
                                mode = 'readwrite',
                                store, request;
    
                            store = db.getObjectStore(mode);
    
                            request = store.delete(id);
    
                            request.onsuccess = callback;
                        });
                    },
    
                    deleteAll: function (callback) {
    
                        db.open(function () {
    
                            var mode, store, request;
    
                            mode = 'readwrite';
                            store = db.getObjectStore(mode);
                            request = store.clear();
    
                            request.onsuccess = callback;
                        });
    
                    }
                };
    
                window.app = window.app || {};
                window.app.db = db;
    
            }(window));
    
    
            //将数据显示在页面上的方法
            var bindData = function (data) {
    
                $("#IndexedDB").html('');
    
                if(data.length === 0){
                    $("#IndexedDB").html("没有数据");
                    return;
                }
    
                data.forEach(function (note) {
                    $("#IndexedDB").append(note.id+","+note.title+","+note.text);
                });
            };
    
            //一个新数据
            var note = 
            {
                    id:1,
                    title: "数据1",
                    text: "数据1的另一个字段"
            };
            //又一个新数据
            var note2 = 
            {
                    id:2,
                    title: "数据2",
                    text: "数据2的另一个字段"
            };
            //插入或更新数据(insert or update)
            window.app.db.save(note,function()
            {
                //window.app.db.getAll(bindData);
            });
            window.app.db.save(note2);
    
            //获取数据
            window.app.db.get(1,function(item)
            {
                //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
            });
    
            //删除数据
            window.app.db.delete(1,function()
            {
                //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
            }); 
    
            //删除所有
            window.app.db.deleteAll(function()
            {
                //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
            });
    
    </script>

    想对IndexedDB更多用法进行了解的可以参考这两篇文章。

    https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB

    http://web.jobbole.com/81793/


    除了IndexedDB以外,还有一种已经被W3C放弃的Web SQL。

    浏览器支持本地数据库并不是从IndexedDB才开始实现,它是在Web SQL实现之后的一种新方法。类似IndexedDB,Web SQL是一个客户端数据库,但它作为一个关系数据库的实现,使用结构化查询语言(SQL)与数据库通信。Web SQL的历史充满了曲折,但底线是没有主流的浏览器厂商对Web SQL继续支持。

    如果Web SQL实际上是一个废弃的技术,为什么还要提它呢?有趣的是,Web SQL在浏览器里得到稳固的支持。Chrome, Safari, iOS Safari, and Android 浏览器都支持。另外,并不是这些浏览器的最新版本才提供支持,许多这些最新最好的浏览器之前的版本也可以支持。有趣的是,如果你为Web SQL添加支持来支持IndexedDB,你突然发现,许多浏览器厂商和版本成为支持浏览器内置数据库的某种化身。

    因此,如果您的应用程序真正需要一个客户端数据库,你想要达到的最高级别的采用可能,当IndexedDB不可用时,也许您的应用程序可能看起来需要选择使用Web SQL来支持客户端数据架构。虽然文档数据库和关系数据库管理数据有鲜明的差别,但只要你有正确的抽象,就可以使用本地数据库构建一个应用程序。

    Web SQL的用法类似于操作SQLite数据库,在这里不展开介绍了。
    想对Web SQL了解更多,可以参考这篇文章:http://www.ibm.com/developerworks/cn/web/1210_jiangjj_html5db/

    (4)文件接口(File API)

    这里写图片描述

    在之前我们操作本地文件都是使用flash、silverlight或者第三方的activeX插件等技术,由于使用了这些技术后就很难进行跨平台、或者跨浏览器、跨设备等情况下实现统一的表现,从另外一个角度来说就是让我们的web应用依赖了第三方的插件,而不是很独立,不够通用。在HTML5标准中,默认提供了操作文件的API让这一切直接标准化。有了操作文件的API,让我们的Web应用可以很轻松的通过JS来控制文件的读取、写入、文件夹、文件等一系列的操作。

    先看一个demo。之前我们操作一个图片文件,都是先将图片上传到服务器端,然后再使用一个img标签指向到服务器的url地址,然后再进行一个使用第三方插件进行图片处理,而现在这一切都不需要服务器端了,因为FileReader对象提供的几个读取文件的方法变得异常简单,而且全部是客户端js的操作。

    http://html5demos.com/file-api/

    现在我们自己来使用这些API。

    先写好我们的HTML页面。

        <input type="file" multiple="multiple" name="fileDemo" id="fileDemo" />
        <br />
        <input type="button" value="获取文件的名字" id="btnGetFile" />
        <input type="button" value="readAsDataURL" id="readAsDataURL" onclick="showDataByURL();" />
        <input type="button" value="readAsBinaryString" id="readAsBinaryString" onclick="showDataByBinaryString();" />
        <input type="button" value="readAsText" id="readAsText" onclick="showDataByText();" />
        <div id="result"></div>

    获取文件名

                $("#btnGetFile").click(function(e)
                {
                    var fileList = document.getElementById("fileDemo").files;
                    for (var i = 0; i < fileList.length; i++)
                    {
                        if (!(/image\/\w+/.test(fileList[i].type)))
                        {
                            $("#result").append("<span>type:" + fileList[i].type + "--******非图片类型*****--name:" + fileList[i].name + "--size:" + fileList[i].size + "</span><br />");
                        }
                        else
                        {
                            $("#result").append("<span>type:" + fileList[i].type + "--name:" + fileList[i].name + "--size:" + fileList[i].size + "</span><br />");
                        }
                    }
                });

    readAsDataURL()

    开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.

    这个方法很有用,比如,可以实现图片的本地预览.

            function showDataByURL()
            {
                var resultFile = document.getElementById("fileDemo").files[0];
                if (resultFile)
                {
                    var reader = new FileReader();
    
                    reader.readAsDataURL(resultFile);
                    reader.onload = function(e)
                    {
                        var urlData = this.result;
                        document.getElementById("result").innerHTML += "<img src='" + urlData + "' alt='" + resultFile.name + "' />";
                    };
    
                }
    
            }

    readAsBinaryString()

    开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据.

    
            function showDataByBinaryString()
            {
                var resultFile = document.getElementById("fileDemo").files[0];
                if (resultFile)
                {
                    var reader = new FileReader();
                    //异步方式,不会影响主线程
                    reader.readAsBinaryString(resultFile);
    
                    reader.onload = function(e)
                    {
                        var urlData = this.result;
                        document.getElementById("result").innerHTML += urlData;
                    };
                }
            }
    

    readAsText()

    开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个字符串以表示所读取的文件内容.

    
            function showDataByText()
            {
                var resultFile = document.getElementById("fileDemo").files[0];
                if (resultFile)
                {
                    var reader = new FileReader();
    
                    reader.readAsText(resultFile, 'gb2312');
                    reader.onload = function(e)
                    {
                        var urlData = this.result;
                        document.getElementById("result").innerHTML += urlData;
                    };
                }
            }

    事件处理程序

    onabort
    当读取操作被中止时调用.
    onerror
    当读取操作发生错误时调用.
    onload
    当读取操作成功完成时调用.
    onloadend
    当读取操作完成时调用,不管是成功还是失败.该处理程序在onload或者onerror之后调用.
    onloadstart
    当读取操作将要开始之前调用.
    onprogress
    在读取数据过程中周期性调用.


    在文件上传时,HTML5还支持拖拽功能。

    这里写图片描述

    <div id="holder"></div> 
    
    var holder = document.getElementById('holder');
    
    holder.ondrop = function (e) 
    {
      e.preventDefault();
    
      var file = e.dataTransfer.files[0],
          reader = new FileReader();
    
      reader.onload = function (event) 
      {
        console.log(event.target);
        holder.style.background = 'url(' + event.target.result + ') no-repeat center';
      };
    
      console.log(file);
      reader.readAsDataURL(file);
    
      return false;
    };

    想对HTML5文件接口操作文件了解更多请参考下面的文章:

    https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications

    https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

    http://blog.csdn.net/testcs_dn/article/details/8695532

    http://www.cnblogs.com/fly_dragon/archive/2012/06/02/2532035.html

    ③ 设备访问特性 (DEVICE ACCESS)

    这里写图片描述

    来一段W3C对这个特性的介绍。

    Beginning with the Geolocation API, Web Applications can present rich, device-aware features and experiences. Incredible device access innovations are being developed and implemented, from audio/video input access to microphones and cameras, to local data such as contacts & events, and even tilt orientation.

    大致包含 地理位置API媒体访问API访问联系人及事件设备方向

    下面分别进行研究。

    (1)地理位置API(Geolocation API)

    这里写图片描述

    HTML5 Geolocation API 用于获得用户的地理位置。
    鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的。一般网页在调用此信息时,会弹出权限申请窗口。

    先上Demo:http://www.w3school.com.cn/tiy/t.asp?f=html5_geolocation_error

    如果电脑获取不到位置信息的话,就在手机上试一下吧。

    getCurrentPosition()

    getCurrentPosition() 方法来获得用户的位置。

    标准用法如下:

    <script>
        var x=document.getElementById("demo");
        function getLocation()
        {
          if (navigator.geolocation)
          {
              navigator.geolocation.getCurrentPosition(showPosition);
          }
          else
          {
              x.innerHTML="Geolocation is not supported by this browser.";
          }
        }
        function showPosition(position)
        {
            x.innerHTML="Latitude: " + position.coords.latitude + "<br />Longitude: " + position.coords.longitude;
        }
    </script>

    -检测是否支持地理定位
    -如果支持,则运行 getCurrentPosition() 方法。如果不支持,则向用户显示一段消息。
    -如果getCurrentPosition()运行成功,则向参数showPosition中规定的函数返回一个coordinates对象
    -showPosition() 函数获得并显示经度和纬度

    上面的例子是一个非常基础的地理定位脚本,不含错误处理。

    完整的处理应该是这样的.

        <script>
            var x = document.getElementById("demo");
            function getLocation()
            {
                if (navigator.geolocation)
                {
                    navigator.geolocation.getCurrentPosition(showPosition, showError);
                }
                else
                {
                    x.innerHTML = "Geolocation is not supported by this browser.";
                }
            }
            function showPosition(position)
            {
                x.innerHTML = "Latitude: " + position.coords.latitude + "<br />Longitude: " + position.coords.longitude;
            }
            function showError(error)
            {
                switch (error.code)
                {
                    case error.PERMISSION_DENIED:
                        x.innerHTML = "User denied the request for Geolocation."
                        break;
                    case error.POSITION_UNAVAILABLE:
                        x.innerHTML = "Location information is unavailable."
                        break;
                    case error.TIMEOUT:
                        x.innerHTML = "The request to get user location timed out."
                        break;
                    case error.UNKNOWN_ERROR:
                        x.innerHTML = "An unknown error occurred."
                        break;
                }
            }
        </script>

    错误代码:
    -Permission denied - 用户不允许地理定位
    -Position unavailable - 无法获取当前位置
    -Timeout - 操作超时
    -Unknown error - 未知错误

    如果想对地理位置API了解更多,可以参考这个网址。http://www.w3school.com.cn/html5/html_5_geolocation.asp

    (2)媒体访问API(media API)

    这里写图片描述

    先上demo。麦克风和摄像头也涉及到用户隐私,所以浏览器会向用户申请访问权限。

    https://www.ganecheng.tech/html5/media.html

    getUserMedia()

    以上的效果,都是通过getUserMedia()方法实现的。

        <video id="video" autoplay="autoplay" style='width: 640px; height: 480px'></video>
        <button id='picture'>PICTURE</button>
        <canvas id="canvas" width="640" height="480"></canvas>
            var video = document.getElementById("video");
            var context = canvas.getContext("2d");
            var errocb = function(code)
            {
                console.log(code);
            };
            if (navigator.getUserMedia)
            { // 标准的API
                navigator.getUserMedia(
                {
                    "video" : true
                }, function(stream)
                {
                    video.src = stream;
                    video.play();
                }, errocb);
            }
            else if (navigator.webkitGetUserMedia)
            { // WebKit 核心的API
    
                console.log(navigator.webkitGetUserMedia);
                navigator.webkitGetUserMedia(
                {
                    "video" : true
                }, function(stream)
                {
    
                    video.src = window.webkitURL.createObjectURL(stream);
                    video.play();
                }, errocb);
    
            }
            //    将拍好的照片显示在画布上
            document.getElementById("picture").addEventListener("click", function()
            {
                context.drawImage(video, 0, 0, 640, 480);
            });

    视频获取就是这个样子,音频获取添加"audio" : true即可。

    想对媒体API了解更多,参考文章:http://blog.csdn.net/u010359143/article/details/50326981

    http://blog.csdn.net/renfufei/article/details/21168239

    http://www.jb51.net/html5/81028.html

    (3)联系人管理API(Contacts Manager API)

    这个纯属于W3C的美好设想,还没有正式纳入标准。目前没有搜到靠谱的资料。

    当初的提议可以参考这里。http://contacts-manager-api.sysapps.org/

    但是有两个类似的变通实现。

    FirefoxOS(已结束生命)示例代码。

    var request = window.navigator.contacts.getAll();
    var count = 0;
    request.onsuccess = function () 
    {
      if(this.result) 
      {
        count++;
        // Display the name of the contact
        console.log(this.result.givenName + ' ' + this.result.familyName);
        // Move to the next contact which will call the request.onsuccess with a new result
        this.continue();
      } else 
      {
        console.log(count + 'contacts found.');
      }
    }
    request.onerror = function () {}

    想要对这个已无生命气息的web操作系统了解更多的参考这里 https://developer.mozilla.org/en-US/docs/Mozilla/B2G_OS/API/ContactManager

    Cordova(Hybrid App)实现方式参考这里https://cordova.apache.org/docs/en/3.0.0/cordova/contacts/contacts.html

    (4)设备方向和运动API(DeviceOrientation & DeviceMotion API)

    这里写图片描述

    DeviceOrientation常用于检测重力感应方向,DeviceMotion常用于摇一摇功能。

    ① DeviceOrientation

    重力感应也是原生APP中经常见到的一个功能,在Web App中的应用多见于判断屏幕的旋转方向,以及在此基础上实现的场景应用,如控制页面上物体的左右移动,加减速等。

    在Web App中实现以上的功能,需要实时获取屏幕的旋转方向参数,这些参数可以从浏览器的利用HTML5的DeviceOrientation API获得。

    当浏览器的Orientation发生变化时,触发DeviceOrientation事件,并返回一个DeviceOrientationEvent对象,其属性列表如下:

    属性释义
    alpha设备指示的方向,根据指南针的设定情况而定
    beta设备绕x轴旋转的角度
    gamma设备绕y轴旋转的角度

    注:不同版本的手机操作系统和浏览器,以及不同的应用程序中内置的浏览器对deviceorientation事件的支持不尽相同。尤其在Android平台上,可能会出现有的设备正常工作,有的则毫无反应的情况。

    工作原理

    根据event对象的三个方向的参数来确定设备的旋转角度。其中,alpha的取值范围是0-360,这个需要根据设备的指南针设定情况而定,一般来说,设备指向正北方向时为0.beta值为设备绕x轴旋转的角度,取值范围为-180-180。gamma取值范围-90-90.

    这里面alpha值的意义并不大,主要参考beta和gamma值。
    当屏幕从水平沿y轴向左倾斜时gamma值变为负值,向右倾斜变为正值。
    档屏幕从水平沿x轴向前倾斜时beta值变为正值,向后倾斜时变为负值。
    所以,如果我们设定一个阈值,当beta和gamma的绝对值大于这个阈值时,我们就认为设备发生了旋转。另外根据beta和gamma的值来判断向左倾斜还是向右倾斜,以及倾斜的程度。

    实现方式和示例

    首先是为浏览器绑定deviceorientation事件和处理程序。

    //add deviceorientation event listener
    if(window.DeviceOrientationEvent)
    {
        window.addEventListener('deviceorientation',DeviceOrientationHandler,false);
    }else
    {
        alert("您的浏览器不支持DeviceOrientation");
    }
    
    function DeviceOrientationHandler(event)
    {
            var alpha = event.alpha,
                beta = event.beta,
                gamma = event.gamma;
    
            if(alpha != null || beta != null || gamma != null)
            {
                dataContainerOrientation.innerHTML = "alpha:" + alpha + "<br />beta:" + beta + "<br />gamma:" + gamma;
                //判断屏幕方向
                var html = "";
                if( Math.abs(gamma) < GAMMA_MIN && Math.abs(beta) > BETA_MAX ){
                    html = "屏幕方向:Portrait";
                }
    
                if( Math.abs(beta) < BETA_MIN && Math.abs(gamma) > GAMMA_MAX ){
                    html = "屏幕方向:Landscape";
                }
    
                var gamma_html = "";
                if( gamma > 0 ){
                    gamma_html = "向右倾斜";
                }else{
                    gamma_html = "向左倾斜";
                }
                html += "<br />"+gamma_html
                stage.innerHTML = html;
            }else
            {
                dataContainerOrientation.innerHTML = "当前浏览器不支持DeviceOrientation";
            }
    }

    这个示例中展示了如何利用beta和gamma值来展示屏幕的旋转方向和侧翻方向。要实现更精确的物体判断,还需要复杂的算法来计算。

    扩展应用

    使用DeviceOrientation API接口可以实现在web中获取手机设备的屏幕旋转方向参数,在示例的基础上进行改进,可以扩展到在屏幕上控制页面元素的移动,实现动画或游戏的目的。例如通过调整屏幕的方向控制页面上的小球走迷宫,控制小车的移动躲避障碍等。

    ② DeviceMotion

    摇一摇功能是很多原生APP都可以实现的功能,如微信中的摇一摇找好友,QQ音乐中的摇一摇换歌等。它们都是利用了手机加速传感器提供的API,当监听到手机加速变化的事件时,根据获取的加速值来执行不同的动作。

    在Web APP中HTML5 也提供了类似的接口,就是DeviceMotionEvent。DeviceMotion封装了运动传感器数据的事件,可以获取手机运动状态下的运动加速度等数据。

    DeviceMotionEvent对象属性列表:

    属性释义
    event.accelarationx(y,z):设备在x(y,z)方向上的移动加速度值
    event.accelarationIncludingGravityx(y,z):考虑了重力加速度后设备在x(y,z)方向上的移动加速度值
    event.rotationRatealpha,beta,gamma:设备绕x,y,z轴旋转的角度

    event.accelarationIncludingGravity与event.accelaration的区别在于前者加入了重力加速度,即在z轴方向加了9.8,在x,y方向上的值两者相同。

    旋转速度rotationRate:alpha、beta、gamma的概念与DeviceOrientationEvent一致。
    区别在于:
    DeviceOrientationEvent的值是相对于初始状态的差值,只要设备方向不变,怎么动都不会影响数值;
    DeviceMotionEvent是相对于之前的某个瞬间值的差值时间比,即变化的速度,一旦设备静止则会恢复为0。

    实现摇一摇

            function Shake(threshold, callback)
            {
                //定义阈值 
                this.SHAKE_THRESHOLD = threshold ? threshold : 2000;
                this.last_update = 0;
                this.x = this.y = this.z = this.last_x = this.last_y = this.last_z = 0;
                this.init = function()
                {
                    if (window.DeviceMotionEvent)
                    {
                        window.addEventListener('devicemotion', this.deviceMotionHandler, false);
                    }
                    else
                    {
                        alert('您的浏览器不支持DeviceMotion');
                    }
                };
                var that = this;
                this.deviceMotionHandler = function(eventData)
                {
                    var acceleration = eventData.accelerationIncludingGravity;
                    var curTime = new Date().getTime();
                    if ((curTime - that.last_update) > 100)
                    {
                        var diffTime = curTime - that.last_update;
                        that.last_update = curTime;
                        that.x = acceleration.x;
                        that.y = acceleration.y;
                        that.z = acceleration.z;
                        var speed = Math.abs(that.x + that.y + that.z - that.last_x - that.last_y - that.last_z) / diffTime * 10000;
                        if (speed > that.SHAKE_THRESHOLD)
                        {
                            if (window.console && console.log)
                            {
                                console.log("shaked");
                            }
                            if (callback != undefined)
                            {
                                callback(that);
                            }
                        }
                        that.last_x = that.x;
                        that.last_y = that.y;
                        that.last_z = that.z;
                    }
                }
            };
    
            window.onload = function()
            {
                var shake1 = new Shake(2000, function(obj)
                {
                    alert("shaked");
                    var r = document.getElementById("result");
                    r.innerHTML = "x:" + obj.x + "";
                    r.innerHTML += "y:" + obj.y + "";
                    r.innerHTML += "z:" + obj.z + "";
                });
                shake1.init();
            };

    设备方向和运动API涉及到一些数学知识。想要对这一API了解更多,可以参考下面两篇文章。

    http://www.jianshu.com/p/5769075e9885

    http://w3c.github.io/deviceorientation/spec-source-orientation.html

    ④ 连接特性(CONNECTIVITY)

    这里写图片描述

    先看W3C的定义。

    More efficient connectivity means more real-time chats, faster games, and better communication. Web Sockets and Server-Sent Events are pushing (pun intended) data between client and server more efficiently than ever before.

    HTTP是无连接的,一次请求,一次响应。想要实现微信网页版扫一扫登录,网页版微信聊天的功能,需要使用轮询的方式达到长连接的效果,轮询的大部分时间是在做无用功,浪费网络,浪费资源。现在HTML5为我们带来了更高效的连接方案 Web SocketsServer-Sent Events

    下面对这两种连接方式分别进行研究。

    (1)网页Sockets(Web Sockets)

    这里写图片描述

    运行原理

    这里写图片描述

    浏览器端示例

    var wsServer = 'ws://localhost:8888/Demo'; //服务器地址
    var websocket = new WebSocket(wsServer); //创建WebSocket对象
    websocket.send("hello");//向服务器发送消息
    alert(websocket.readyState);//查看websocket当前状态
    websocket.onopen = function (evt) 
    {
    //已经建立连接
    };
    websocket.onclose = function (evt) 
    {
    //已经关闭连接
    };
    websocket.onmessage = function (evt) 
    {
    //收到服务器消息,使用evt.data提取
    };
    websocket.onerror = function (evt) 
    {
    //产生异常
    }; 

    服务器端

    握手协议的客户端数据已经由浏览器代劳了,服务器端需要我们自己来实现,目前市场上开源的实现也比较多如:

    Kaazing WebSocket Gateway(一个 Java 实现的 WebSocket Server);
    mod_pywebsocket(一个 Python 实现的 WebSocket Server);
    Netty(一个 Java 实现的网络框架其中包括了对 WebSocket 的支持);
    node.js(一个 Server 端的 JavaScript 框架提供了对 WebSocket 的支持);
    WebSocket4Net(一个.net的服务器端实现);
    

    其实在目前的.net4.5框架中已经实现了WebSocket,不用官方实现,我们自己来写个简单的。服务器端需要根据协议来握手、接收和发送。

    握手

    /// <summary>
    /// 生成Sec-WebSocket-Accept
    /// </summary>
    /// <param name="handShakeText">客户端握手信息</param>
    /// <returns>Sec-WebSocket-Accept</returns>
    private static string GetSecKeyAccetp(byte[] handShakeBytes,int bytesLength)
    {
        string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0, bytesLength);
        string key = string.Empty;
        Regex r = new Regex(@"Sec-WebSocket-Key:(.*?)rn");
        Match m = r.Match(handShakeText);
        if (m.Groups.Count != 0)
        {
            key = Regex.Replace(m.Value, @"Sec-WebSocket-Key:(.*?)rn", "$1").Trim();
        }
        byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
        return Convert.ToBase64String(encryptionString);
    }

    如果握手成功,将会触发客户端的onopen事件。

    解析接收的客户端信息

    /// <summary>
    /// 解析客户端数据包
    /// </summary>
    /// <param name="recBytes">服务器接收的数据包</param>
    /// <param name="recByteLength">有效数据长度</param>
    /// <returns></returns>
    private static string AnalyticData(byte[] recBytes, int recByteLength)
    {
        if (recByteLength < 2) { return string.Empty; }
    
        bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧
        if (!fin){
        return string.Empty;// 超过一帧暂不处理
        }
    
        bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码
        if (!mask_flag){
        return string.Empty;// 不包含掩码的暂不处理
        }
    
        int payload_len = recBytes[1] & 0x7F; // 数据长度
    
        byte[] masks = new byte[4];
        byte[] payload_data;
    
        if (payload_len == 126)
        {
            Array.Copy(recBytes, 4, masks, 0, 4);
            payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
            payload_data = new byte[payload_len];
            Array.Copy(recBytes, 8, payload_data, 0, payload_len);
    
        }
        else if (payload_len == 127)
        {
            Array.Copy(recBytes, 10, masks, 0, 4);
            byte[] uInt64Bytes = new byte[8];
            for (int i = 0; i < 8; i++)
            {
            uInt64Bytes[i] = recBytes[9 - i];
            }
            UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
    
            payload_data = new byte[len];
            for (UInt64 i = 0; i < len; i++)
            {
            payload_data[i] = recBytes[i + 14];
            }
        }else
        {
            Array.Copy(recBytes, 2, masks, 0, 4);
            payload_data = new byte[payload_len];
            Array.Copy(recBytes, 6, payload_data, 0, payload_len);
    
        }
    
        for (var i = 0; i < payload_len; i++)
        {
        payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
        }
        return Encoding.UTF8.GetString(payload_data);
    }

    发送数据至客户端

    /// <summary>
    /// 打包服务器数据
    /// </summary>
    /// <param name="message">数据</param>
    /// <returns>数据包</returns>
    private static byte[] PackData(string message)
    {
        byte[] contentBytes = null;
        byte[] temp = Encoding.UTF8.GetBytes(message);
    
        if (temp.Length < 126)
        {
            contentBytes = new byte[temp.Length + 2];
            contentBytes[0] = 0x81;
            contentBytes[1] = (byte)temp.Length;
            Array.Copy(temp, 0, contentBytes, 2, temp.Length);
        }else if (temp.Length < 0xFFFF)
        {
            contentBytes = new byte[temp.Length + 4];
            contentBytes[0] = 0x81;
            contentBytes[1] = 126;
            contentBytes[2] = (byte)(temp.Length & 0xFF);
            contentBytes[3] = (byte)(temp.Length >> 8 & 0xFF);
            Array.Copy(temp, 0, contentBytes, 4, temp.Length);
        }else
        {
        // 暂不处理超长内容
        }
    
        return contentBytes;
    }

    Web Sockets 是一个非常棒的设计,想要了解更多,参考这里。

    https://my.oschina.net/u/1266171/blog/357488

    (2)服务器发送事件(Server-Sent Events)

    这里写图片描述

    运行原理

    这里写图片描述

    浏览器通过HTTP向服务器发送请求,服务器端拿出数据库中的最新的信息,立即返回给客户端,客户端等待三秒后再次发出下一个请求。

    客户端示例

    <script>
    if(typeof(EventSource)!=="undefined")
    {
      var source=new EventSource("/example/html5/demo_sse.php");
      source.onmessage=function(event)
        {
        document.getElementById("result").innerHTML+=event.data + "<br />";
        };
    }
    else
    {
      document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
    }
    </script>

    服务器端示例

    <?php
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    
    $time = date('r');
    echo "data: The server time is: {$time}\n\n";
    flush();
    ?>

    想要对Server-Sent Events了解更多的,可以参考这两篇文章。

    http://www.w3school.com.cn/html5/html_5_serversentevents.asp

    http://www.ibm.com/developerworks/cn/web/1307_chengfu_serversentevent/


    服务器负载

    -Long-polling占一小部分CPU资源,但是创建空的进程将浪费系统的内存
    -Server-Sent Events工作的方式有很多,除非Server-Sent Events不必在每一次响应发出后都关闭连接。
    -WebSockets,服务器只需要一个进程处理所有的请求,没有循环,不必为每个客户端都分配cpu和内存。

    客户端负载

    -Long-polling取决于实现方式,但终究是一个异步的方式
    -Server-Sent Events采用浏览器的内置的实现方式,只花费很少的一部分资源。
    -WebSockets跟Server-Sent Events一样,采用浏览器的内置的实现方式,只花费很少的一部分资源。

    时间线

    -Long-polling接近实时,但是发送新的请求和发送相应会有一定的时延。
    -Server-Sent Events默认延时3秒,但是可以调整。
    -WebSockets真正的实时

    实现方式复杂度

    -Long-polling实现起来非常简单
    -Server-Sent Events甚至比Long-polling更简单
    -需要一个WebSockets服务器处理事件,并开放一个端口


    想要对轮询,Web Sockets,Server-Sent Events三者的区别有所了解的,可以参考这篇文章。

    https://www.oschina.net/question/82993_63312

    ⑤ 网页多媒体特性(MULTIMEDIA)

    这里写图片描述

    看一下W3C的定义。

    Audio and video are first class citizens in the HTML5 web, living in harmony with your apps and sites. Lights, camera, action!

    看的出来HTML5原生支持音视频让W3C很兴奋。也是广大开发者多年的期待。终于可以将Flash踹入茅坑了。

    Audio 和 Video 标签

    这里写图片描述

    这里写图片描述

    虽然支持音视频很强大,但是确实没有什么好说的,就是两个标签。

    <audio controls="controls">
      <source src="song.ogg" type="audio/ogg">
      <source src="song.mp3" type="audio/mpeg">
      Your browser does not support the audio tag.
    </audio>
    <video width="320" height="240" controls="controls">
      <source src="movie.ogg" type="video/ogg">
      <source src="movie.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>

    但是由于音视频相对于其他新特性来说会被更多的使用,各个浏览器的兼容问题应该引起开发者的重视。统一各平台的播放器ckplayer值得借鉴。可以参考此网页http://www.ckplayer.com/

    Audio API

    这里写图片描述

    HTML5 音频处理接口与Audio标签是不一样的。页面上的Audio标签只是HTML5更语义化的一个表现,而HTML5提供给JavaScript编程用的Audio API则让我们有能力在代码中直接操作原始的音频流数据,对其进行任意加工再造。

    先上demo,http://wayou.github.io/HTML5_Audio_Visualizer/,打开页面之后,打开一首本地歌曲。然后可以显示可视化效果。

    原理

    一段音频到达扬声器进行播放之前,半路对其进行拦截,于是我们就得到了音频数据了,这个拦截工作是由window.AudioContext来做的,我们所有对音频的操作都基于这个对象。通过AudioContext可以创建不同各类的AudioNode,即音频节点,不同节点作用不同,有的对音频加上滤镜比如提高音色(比如BiquadFilterNode),改变单调,有的音频进行分割,比如将音源中的声道分割出来得到左右声道的声音(ChannelSplitterNode),有的对音频数据进行频谱分析。

    所有的操作都是基于AudioContext这个对象进行的。

    得到AudioContext对象。

    window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
    
    try {
        var audioContext = new window.AudioContext();
    } catch (e) {
        Console.log('!Your browser does not support AudioContext');
    }

    后续的操作,都是与音频解码相关的。想要了解更多HTML5 Audio API。可以参考下面的文章。

    http://www.cnblogs.com/Wayou/p/3543577.html

    https://developer.mozilla.org/zh-CN/docs/Web/API/AudioContext

    搜索了一下,并没有找到与Audio API这么强大的功能同一级别的Video API。

    ⑥ 三维、图形及特效特性(3D, Graphics & Effects)

    这里写图片描述

    来看W3C的介绍。

    Between SVG, Canvas, WebGL, and CSS3 3D features, you’re sure to amaze your users with stunning visuals natively rendered in the browser.

    大致包含SVG, Canvas, WebGL, 和 CSS3 3D,下面分别进行研究。

    (1)可缩放矢量图形(SVG)

    这里写图片描述

    SVG是用于描述二维矢量图形的一种图形格式。

    先上demo,http://www.ganecheng.tech/html5/svg.html

    与其他图像格式相比,使用 SVG 的优势在于:
    -SVG 可被非常多的工具读取和修改(比如记事本)
    -SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
    -SVG 是可伸缩的
    -SVG 图像可在任何的分辨率下被高质量地打印
    -SVG 可在图像质量不下降的情况下被放大
    -SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
    -SVG 可以与 Java 技术一起运行
    -SVG 是开放的标准
    -SVG 文件是纯粹的 XML

    SVG有三种用法。

    ① 把SVG直接当成图片放在网页上

    <img style="width: 250px;" alt="kiwi" src="./kiwi.svg">

    ② SVG动画

    画一个五角星

    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190">
       <polygon points="100,10 40,180 190,60 10,60 160,180"
       style="fill:red;stroke:blue;stroke-width:3;fill-rule:evenodd;" />
    </svg>

    ③ SVG图片的交互和滤镜效果

    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="612px" height="502.174px" viewBox="0 65.326 612 502.174"
            enable-background="new 0 65.326 612 502.174" xml:space="preserve" class="logo99">
        <style>
        .kiwi {
            fill: #94d31b; //
            stroke: #909; //
            stroke-width: 10; // not sure which of these is correct //
            stroke-linejoin : butt | round | square; //
            stroke-linecap: butt| round| square; //
            stroke-dasharray: 5, 5, 10; //
            filter: url(#pictureFilter); //
            mask: url(#f1); //
            clip-path: url();
        }
    
        .kiwi:hover {
            fill: #ace63c;
        }
    
        .ground {
            fill: #787f6a;
        }
    
        .ground:hover {
            filter: url(#pictureFilter);
            fill: #896d3d;
        }
        </style>
        <ellipse class="ground" cx="283.5" cy="487.5" rx="259" ry="80"></ellipse>
        <path class="kiwi"
                    d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
          c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
          c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
          c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
          c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
          c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
          c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
          c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
          c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
          c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
          c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
          c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
          c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
          c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
          z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
          C434.693,207.929,439.613,203.01,445.731,203.01z">
        </path>
        <filter id="pictureFilter">
          <feGaussianBlur stdDeviation="15"></feGaussianBlur>
        </filter>
    </svg>

    如何用SVG画出一条会动的线

    先看demo,http://www.ganecheng.tech/html5/svg_animate_line.html

    <path fill="none" stroke="deeppink" stroke-width="14" stroke-miterlimit="0"
    
    d="M11.6 269s-19.7-42.4 6.06-68.2 48.5-6.06 59.1 12.1l-3.03 28.8 209-227s45.5-21.2 60.6 1.52c15.2 22.7-3.03 47-3.03 47l-225 229s33.1-12 48.5 7.58c50 63.6-50 97-62.1 37.9"
    
    stroke-dasharray="988.0 988.0"
    
    stroke-dashoffset="988.0"
    
    />
    var path = document.querySelector('.squiggle-animated path');
    var length = path.getTotalLength();
    // 清除之前的动作
    path.style.transition = path.style.WebkitTransition =
      'none';
    // 设置起始点
    path.style.strokeDasharray = length + ' ' + length;
    path.style.strokeDashoffset = length;
    // 获取一个区域,获取相关的样式,让浏览器寻找一个起始点。
    path.getBoundingClientRect();
    // 定义动作
    path.style.transition = path.style.WebkitTransition =
      'stroke-dashoffset 2s ease-in-out';
    // Go!
    path.style.strokeDashoffset = '0';

    原理:使用d属性得到一条贝塞尔曲线,使每段线段间距值为线段的1倍长度,慢慢降低偏移值,得到正向的移动效果。

    属性stroke-dasharray是让你指定画出的线段每段的长度,第二个值是各段之间空隙的长度。
    属性stroke-dashoffset是让你指定每个小段的起始偏移量。

    想对SVG了解更多的,可以参考下面的网址。

    http://www.w3school.com.cn/svg/svg_examples.asp

    http://www.w3school.com.cn/svg/svg_reference.asp

    http://www.webhek.com/svg

    http://www.webhek.com/animated-line-drawing-in-svg/

    http://www.webhek.com/demo/svg/

    (2)画布(Canvas)

    这里写图片描述

    Canvas也是前端工程师炫技的最热门的阵地。有许多demo。

    http://www.17sucai.com/pins/demoshow/9386
    http://www.17sucai.com/pins/demoshow/12676
    http://www.17sucai.com/pins/demoshow/5937
    http://www.html5tricks.com/demo/html5-canvas-waterful/index.html
    http://www.html5tricks.com/demo/html5-canvas-loader/index.html
    http://www.html5tricks.com/demo/html5-canvas-particle-effect/index.html
    http://www.html5tricks.com/demo/html5-cool-fire-effect/index.html

    HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。
    画布是一个矩形区域,您可以控制其每一像素。
    canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

    创建 Canvas 元素

    <canvas id="myCanvas" width="200" height="100"></canvas>

    通过 JavaScript 来绘制

    canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:

    <script type="text/javascript">
        var c=document.getElementById("myCanvas");
        var cxt=c.getContext("2d");
        cxt.fillStyle="#FF0000";
        cxt.fillRect(0,0,150,75);
    </script>

    Canvas 与 SVG 对比

    Canvas 和 SVG 都允许您在浏览器中创建图形,但是它们在根本上是不同的。

    SVG

    SVG 是一种使用 XML 描述 2D 图形的语言。
    SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。
    在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

    Canvas

    Canvas 通过 JavaScript 来绘制 2D 图形。
    Canvas 是逐像素进行渲染的。
    在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。

    Canvas 与 SVG 的比较

    Canvas
    -依赖分辨率
    -不支持事件处理器
    -弱的文本渲染能力
    -能够以 .png 或 .jpg 格式保存结果图像
    -最适合图像密集型的游戏,其中的许多对象会被频繁重绘

    SVG
    -不依赖分辨率
    -支持事件处理器
    -最适合带有大型渲染区域的应用程序(比如谷歌地图)
    -复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
    -不适合游戏应用

    想对Canvas了解更多的,可以参考下面链接。

    http://www.w3school.com.cn/html/html5_canvas.asp

    http://www.w3school.com.cn/tags/html_ref_canvas.asp

    https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API

    http://blog.csdn.net/clh604/article/details/8536059

    (3)网页图形库(WebGL)

    这里写图片描述

    先上demo。

    https://www.cubeslam.com/ncokau

    http://labs.gooengine.com/pearl-boy/indexBelow.html

    http://www.cnblogs.com/lhb25/p/9-mind-blowing-webgl-demos.html

    http://www.open-open.com/news/view/9d8136/

    http://www.oschina.net/news/26547/webgl-chrome/

    WebGL(全写Web Graphics Library)是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。

    WebGL 基本原理

    WebGL 的出现使得在浏览器上面实时显示 3D 图像成为现实,WebGL 本质上是基于光栅化的 API ,而不是基于 3D 的 API。

    WebGL对象获取

    WebGL也是基于Canvas画布做的,下面看一下WebGL获取方法。

    // Get A WebGL context
    var canvas = document.getElementById("canvas");
    var gl = canvas.getContext("experimental-webgl");

    WebGL 只关注两个方面,即投影矩阵的坐标和投影矩阵的颜色。使用 WebGL 程序的任务就是实现具有投影矩阵坐标和颜色的 WebGL 对象即可。可以使用“着色器”来完成上述任务。顶点着色器可以提供投影矩阵的坐标,片段着色器可以提供投影矩阵的颜色。

    无论要实现的图形尺寸有多大,其投影矩阵的坐标的范围始终是从 -1 到 1 。下面是一个关于实现 WebGL 对象的一个简单例子。

    // Get A WebGL context
    var canvas = document.getElementById("canvas");
    var gl = canvas.getContext("experimental-webgl");
    
    // setup a GLSL program
    var program = createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    gl.useProgram(program);
    
    // look up where the vertex data needs to go.
    var positionLocation = gl.getAttribLocation(program, "a_position");
    
    // Create a buffer and put a single clipspace rectangle in
    // it (2 triangles)
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
    -1.0, -1.0,
     1.0, -1.0,
    -1.0,  1.0,
    -1.0,  1.0,
     1.0, -1.0,
     1.0,  1.0]),
    gl.STATIC_DRAW);
    gl.enableVertexAttribArray(positionLocation);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
    
    // draw
    gl.drawArrays(gl.TRIANGLES, 0, 6);   

    下面是两个着色器。

    <script id="2d-vertex-shader" type="x-shader/x-vertex">
    attribute vec2 a_position;
    
    void main() {
      gl_Position = vec4(a_position, 0, 1);
    }
    </script>
    
    <script id="2d-fragment-shader" type="x-shader/x-fragment">
    void main() {
      gl_FragColor = vec4(0, 1, 0, 1);  // green
    }
    </script>    

    它将绘出一个绿色的长方形来填充整个画板。

    这里写图片描述

    再往后面实在是太过专业了,需要掌握图形图像学的知识,通过demo确实能看出来非常强大,但是需要更专业的人才能搞了。

    想对WebGL了解更多,参考这里。

    https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

    http://blog.csdn.net/column/details/webgl.html

    http://www.w3cschool.cn/webgl/i4gf1oh1.html

    http://blog.163.com/hongshaoguoguo@126/blog/static/18046981201311310510380/

    (4)CSS3 3D(CSS3 3D)

    这里写图片描述

    先上demo。

    http://www.ganecheng.tech/html5/css33d.html

    CSS3允许元素以3D的形式显示。

    下面讲解一下这个demo是怎样显示出来的。

    <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <style type="text/css">
    *{margin: 0;padding: 0;}
    html,body{height: 80%;background: black;}
    .wrap
    {
          height: 100%;position: relative;
          -webkit-transform-style:preserve-3d;
          -webkit-perspective:0px;
    
          -moz-transform-style:preserve-3d;
          -moz-perspective:0px;
    
          -webkit-animation:mydhua 5s ease infinite;
          -moz-animation:mydhua 5s ease infinite;
    }
    .box
    {
        width: 200px;
        height: 200px;
        position: absolute;
        top: 50%;
        left: 50%;
        margin:-100px 0 0 -100px;
        line-height: 200px;
        text-align: center;
        font-size: 48px;
        color: white;
    }
    .box1{
        -webkit-transform:rotatey(90deg) translatez(-100px);
        -moz-transform:rotatey(90deg) translatez(-100px);
        background: rgba(128,0,128,.5);
    }
    .box2{
        -webkit-transform:rotatey(90deg) translatez(100px);
        -moz-transform:rotatey(90deg) translatez(100px);
        background: rgba(255,0,255,.5);
    }
    .box3{
        -webkit-transform:rotatex(90deg) translatez(100px);
        -moz-transform:rotatex(90deg) translatez(100px);
        background: rgba(255,153,204,.5);
    }
    .box4{
        -webkit-transform:rotatex(90deg) translatez(-100px);
        -moz-transform:rotatex(90deg) translatez(-100px);
        background: rgba(0,204,255,.5);
    }
    .box5{
        -webkit-transform: translatez(-100px);
        -moz-transform:translatez(-100px);
        background: rgba(153,204,255,.5);
    }
    .box6{
        -webkit-transform: translatez(100px);
        -moz-transform:translatez(100px);
        background: rgba(0,255,255,.5);
    }
    
    @-webkit-keyframes mydhua{
    
        0%{-webkit-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg);-webkit-transform-origin: center center;}
        100%{-webkit-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg);-webkit-transform-origin: center center; }
    }
    @-moz-keyframes mydhua{
    
        0%{-moz-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg);-webkit-transform-origin: center center;}
        100%{-moz-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg); -webkit-transform-origin: center center;}
    }
    </style>
    </head>
    <body style="width:960px;margin:0px auto;">
    
    <div class="wrap">
        <div class="box1 box">1</div>
        <div class="box2 box">2</div>
        <div class="box3 box">3</div>
        <div class="box4 box">4</div>
        <div class="box5 box">5</div>
        <div class="box6 box">6</div>
    </div>
    
    <script type="text/javascript">
    
    </script>
    </body>
    </html>

    首先是使子元素可以以3D的效果显示出来。

    .wrap
    {
          height: 100%;position: relative;
          -webkit-transform-style:preserve-3d;
          -webkit-perspective:0px;
    
          -moz-transform-style:preserve-3d;
          -moz-perspective:0px;
    }

    接下来规定6个div的初始位置。
    rotateX()表示沿 X 轴的 3D 旋转角度。
    rotateY()表示沿 Y 轴的 3D 旋转角度。
    translateZ() 表示 3D 转化,仅使用用于 Z 轴的值。表示在Z轴的移动位置,值越大,离屏幕越近,值越小,离屏幕越远。在此网址感受一下translateZ()的效果。http://www.zhangxinxu.com/study/201209/transform-perspective-translateZ.html

        <div class="box1 box">1</div>
        <div class="box2 box">2</div>
        <div class="box3 box">3</div>
        <div class="box4 box">4</div>
        <div class="box5 box">5</div>
        <div class="box6 box">6</div>
    
    .box
    {
        width: 200px;
        height: 200px;
        position: absolute;
        top: 50%;
        left: 50%;
        margin:-100px 0 0 -100px;
        line-height: 200px;
        text-align: center;
        font-size: 48px;
        color: white;
    }
    .box1{
        -webkit-transform:rotatey(90deg) translatez(-100px);
        -moz-transform:rotatey(90deg) translatez(-100px);
        background: rgba(128,0,128,.5);
    }
    .box2{
        -webkit-transform:rotatey(90deg) translatez(100px);
        -moz-transform:rotatey(90deg) translatez(100px);
        background: rgba(255,0,255,.5);
    }
    .box3{
        -webkit-transform:rotatex(90deg) translatez(100px);
        -moz-transform:rotatex(90deg) translatez(100px);
        background: rgba(255,153,204,.5);
    }
    .box4{
        -webkit-transform:rotatex(90deg) translatez(-100px);
        -moz-transform:rotatex(90deg) translatez(-100px);
        background: rgba(0,204,255,.5);
    }
    .box5{
        -webkit-transform: translatez(-100px);
        -moz-transform:translatez(-100px);
        background: rgba(153,204,255,.5);
    }
    .box6{
        -webkit-transform: translatez(100px);
        -moz-transform:translatez(100px);
        background: rgba(0,255,255,.5);
    }

    现在定义关键帧动画。
    用@keyframes定义一个关键帧动画,0%表示起始状态,100%表示结束状态,还可以根据需要定义50%等等。动画的名称叫mydhua。

    @-webkit-keyframes mydhua{
    
        0%{-webkit-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg);-webkit-transform-origin: center center;}
        100%{-webkit-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg);-webkit-transform-origin: center center; }
    }
    @-moz-keyframes mydhua{
    
        0%{-moz-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg);-webkit-transform-origin: center center;}
        100%{-moz-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg); -webkit-transform-origin: center center;}
    }

    接下来就是使用动画。

    .wrap
    {
          -webkit-animation:mydhua 5s ease infinite;
          -moz-animation:mydhua 5s ease infinite;
    }

    这样我们就得到了一个CSS3 3D旋转的效果。

    只要涉及到3D,都和空间立体几何相关。如果想往这方面更进一步发展,桌前要常备这一类的书籍。

    想要对CSS3 3D了解更多的,可以参考下面网址。

    https://segmentfault.com/a/1190000003843764

    http://www.w3school.com.cn/css3/css3_3dtransform.asp

    http://www.cnblogs.com/duanhuajian/archive/2012/08/30/2664026.html

    ⑦ 性能与集成特性(Performance & Integration)

    这里写图片描述

    看看W3C的介绍。

    Make your Web Apps and dynamic web content faster with a variety of techniques and technologies such as Web Workers and XMLHttpRequest 2. No user should ever wait on your watch.

    性能与集成特性主要包括两个东西,Web WorkersXMLHttpRequest 2

    下面依次介绍。

    (1)网页后台任务(Web Workers)

    这里写图片描述

    先上demo,http://www.w3school.com.cn/tiy/t.asp?f=html5_webworker

    当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。

    Ajax向服务器端发送请求,是异步接收响应的。不然页面会卡住。

    Web Workers 是运行在浏览器后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 Web Workers 在后台运行。

    setInterval和setTimeout是单线程执行的。

    虽然在JavaScript中有setInterval和setTimeout函数使javaScript看起来好像使多线程执行,单实际上JavaScript是单线程的,一次只能做一件事情。

    看一个例子。

    <!DOCTYPE html>
    <html>
    <head>
        <title>Web Workers</title>
    </head>
    <body>
        <h1>Web Workers</h1>
    
        <script type="text/javascript">
        setTimeout(function(){
            console.log('timeout function');
        },1000);
        alert('do not close');
        </script>
    </body>
    </html>

    页面一运行就会弹出一个对话框,如果setTimeout是在另外一个线程运行,那么过一秒钟控制台就会打印“timeout function”,事实是只要不关闭对话框,控制台永远不会输出文字,这两句话确实是在一个线程内运行的。

    这样的设计使JavaScript比较简单,但有时候也很令人烦恼,因为单线程的设计意味着JavaScript代码必须很快运行完,常见的问题就是一段复杂的JavaScript脚本会中断页面其它脚本执行,甚至会出现页面失去响应,这也就是为什么Ajax的API要设计成异步的。

    Web Workers 用法

    在html5规范中引入了web workers概念,解决客户端JavaScript无法多线程的问题,其定义的worker是指代码的并行线程,不过web worker处于一个自包含的环境中,无法访问主线程的window对象和document对象,和主线程通信只能通过异步消息传递机制。

    我们需要把希望单独执行的javascript代码放到一个单独的js文件中,然后在页面中调用Worker构造函数来创建一个线程,参数是该文件路径,参数存放如果是相对地址,那么要以包含调用Worker构造函数语句所在脚本为参照,如果是绝对路径,需要保证同源(协议+主机+端口)。这个文件不需要我们在页面使用script标签显示引用

    w=new Worker("/example/html5/demo_workers.js");

    worker对象只有两个属性,其实是两个回调函数句柄。

    onerror:当worker运行出现错误,并且没有在worker中被捕获,会在此捕获
    onmessage:当worker向主线程发送消息是调用
    在其prototype内有两个重要方法

    postMessage:很熟悉的赶脚,之前我们介绍过window对象的postMessage()方法,woker的postMessage方法和window的比较类似,但参数略有不同,只需要传递消息内容就可以,而且支持所有JavaScript原生数据类型,当然不放心的话同样也可以序列化为字符串传递
    terminate:终止worker执行,有些worker执行比较慢,主线程可以主动终止其执行

    demo_workers.js

    var i=0;
    
    function timedCount()
    {
        i=i+1;
        postMessage(i);
        setTimeout("timedCount()",500);
    }
    
    timedCount();

    demo.html

    <!DOCTYPE html>
    <html>
    <body>
    
    <p>计数: <output id="result"></output></p>
    <button onclick="startWorker()">开始 Worker</button> 
    <button onclick="stopWorker()">停止 Worker</button>
    <br /><br />
    
    <script>
    var w;
    
    function startWorker()
    {
        if(typeof(Worker)!=="undefined")
        {
              if(typeof(w)=="undefined")
              {
                  w=new Worker("/example/html5/demo_workers.js");
              }
              w.onmessage = function (event) 
              {
                document.getElementById("result").innerHTML=event.data;
              };
        }
        else
        {
          document.getElementById("result").innerHTML="Sorry, your browser does not support Web Workers...";
        }
    }
    
    function stopWorker()
    { 
        w.terminate();
    }
    </script>
    
    </body>
    </html>
    

    想对 Web Workers 了解更多的,参考下面链接。

    http://www.w3school.com.cn/html5/html_5_webworkers.asp

    http://www.cnblogs.com/dolphinX/p/3452684.html

    https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers

    (2)新的Ajax(XMLHttpRequest 2)

    这里写图片描述

    XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信。也就是Ajax。

    上一代Ajax有以下缺点。

    • 只支持文本数据的传送,无法用来读取和上传二进制文件。
    • 传送和接收数据时,没有进度信息,只能提示有没有完成。
    • 受到”同域限制”(Same Origin Policy),只能向同一域名的服务器请求数据,不能跨域。

    XMLHttpRequest 2也就是新的Ajax。针对老版本的缺点,做出了大幅改进,有下面的特点。

    • 可以设置HTTP请求的时限。
    • 可以使用FormData对象管理表单数据。
    • 可以上传文件。
    • 可以请求不同域名下的数据(跨域请求)。
    • 可以获取服务器端的二进制数据。
    • 可以获得数据传输的进度信息。

    XMLHttpRequest 2示例

    前台代码.

    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>第二代XmlHttpRequest异步上传</title>
            <script type="text/javascript">
                function upload(){
                    if (!window.FormData){
                        alert('您的浏览器不支持第二代XmlHttpRequest');
                        return;
                    }
                    // HTML5 新增对象
                    var formData = new FormData(document.getElementById('uploadForm'));
                    //添加其他表单域
                    formData.append('user', 'haolin');
                    formData.append('pass', '111111');
    
                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', 'upload'); //请求url
    
                    //上传完成回调函数
                    xhr.onload = function(event) {
                        if (xhr.status === 200) {
                            alert("上传成功");
                        } else {
                            alert('出错了');
                        }
                    };
                    xhr.send(formData);
                }
            </script>
        </head>
        <body>
            <h1>第二代XmlHttpRequest对象实现异步上传</h1>
            <form id="uploadForm" action="" method="post" enctype="multipart/form-data">
                <input id="upfile" type="file" name="upfile"/>
                <input type="button" value="上传" onclick="upload()"/> 
            </form>
        </body>
    </html>

    后台代码

    PrintWriter out = new PrintWriter(response.getOutputStream());
    FileItemFactory factory = new DiskFileItemFactory();// 为该请求创建一个DiskFileItemFactory对象,通过它来解析请求。执行解析后,所有的表单项目都保存在一个List中。
    ServletFileUpload upload = new ServletFileUpload(factory);
    List<FileItem> items;
    try {
        items = upload.parseRequest(request);
        Iterator<FileItem> itr = items.iterator();
        while (itr.hasNext()) {
        FileItem item = (FileItem) itr.next();
        System.out.println("是否是FormField: " + item.isFormField());
        System.out.println("接收到域: " + item.getFieldName());
        System.out.println("接收到值: " + item.getString("utf-8"));
        // 检查当前项目是普通表单项目还是上传文件。
        if (item.isFormField()) {// 如果是普通表单项目,显示表单内容。
            String fieldName = item.getFieldName();
            out.println("the field name is " + fieldName);// 显示表单域名称。
           } else {// 如果是上传文件,显示文件名。
            out.println("the upload file name is " + item.getName());
        } 
        }
        out.flush();
        out.close();
    } catch (FileUploadException e) {
        e.printStackTrace();
    }

    对XMLHttpRequest 2进行封装。

    var AjaxForm = function(cfg){
        if (!window.FormData){
            alert("Sorry, your browser doesn't supoort FormData!");
        }
    
        /**
         * null or undefined 返回true, 否则false
         */
        this.isNullOrUndefined = function(v, errMsg){
            if (!v){
                alert(errMsg);
                return true;
            }
            return false;
        };
    
        var cfg = cfg || {};
        if (this.isNullOrUndefined(cfg.id, "id can't be empty")) return;
        if (this.isNullOrUndefined(cfg.url, "url can't be empty")) return;
    
        this.id = cfg.id; // 表单id
        this.method = cfg.method || "POST"; //默认POST方法
        this.url = cfg.url;
        this.async = !cfg.sync; //同步否
        this.resultType = cfg.resultType || "text"; //返回结果类型 json对象或text
        this.formData = new FormData(document.getElementById(this.id)); //form数据
        this.xhr = new XMLHttpRequest(); //当前请求对象
    
        /**
         * 超时事件
         * 配置格式:
         *   timeout : xxx,
         *   onTimeout: function(event){}
         */
        if (cfg.timeout){ 
            this.xhr.timeout = cfg.timeout;
            this.xhr.ontimeout = cfg.onTimeout;
        }
    
        /**
         * 发送过程事件
         * 配置格式: 
         * onProgress: function(loaded, total){}
         */
        if (cfg.onProgress){ //发送数据过程
            this.xhr.upload.onprogress = function(e){
                if (e.lengthComputable) {
                    cfg.onProgress(e.loaded, e.total);
                }
            };
        }
    
        /**
         * 上传完成事件
         */
        if (cfg.onComplete){
            this.xhr.onload = function(event){
                var res = event.target.responseText;
                if (this.resultType === 'json'){
                    if ((typeof JSON) === 'undefine'){
                        res = eval("("+res+")");
                    } else{
                        res = JSON.parse(res);
                    }
                }
                cfg.onComplete(res);
            };
        }
    
        /**
         * 发出请求
         */
        this.request = function(){
            this.xhr.open(this.method, this.url, this.async);
            this.xhr.send(this.formData);
        };
    };
    

    调用

    var af = new AjaxForm({
        id: "uploadForm",
        url: 'upload',
        method: 'POST',
        timeout: 5000,
        onTimeout: function(event){
            alert('It is timeout.');
        },
        onProgress: function(loaded, total){
            var complete = (loaded / total * 100 | 0);
            var progress = document.getElementById('uploadProgress');
            progress.value = complete;
            progress.innerHTML = complete;
        },
        onComplete: function(result){
            alert(result);
        }
    });
    af.request();

    可以看出,虽然是XMLHttpRequest 2,但是还是XMLHttpRequest对象。使用新的特性,需要先判断是否支持window.FormData。

    如果想对XMLHttpRequest 2了解更多,可以参考下面文章。

    https://www.w3.org/TR/XMLHttpRequest2

    https://my.oschina.net/indestiny/blog/215472

    http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html

    http://blog.csdn.net/hills/article/details/41246939


    后记

    之前一直在做web开发。但是从来没有对HTML5仔细研究过,写这篇文章,前前后后花了4天时间,从惊叹于HTML5的强大,到目睹有这么多的坑,浏览器的性能也跟不上。

    但是我们不应该悲观,解决方法总比困难多,Chrome和Firefox也一直在推动浏览器性能提升。前端再也不是切个图,调调颜色,改改字体大小,放个Flash的时代了。HTML5会给我们一个更加美好的未来,前端开发者也有一个提升技术含量,迎接各种机遇的机会了。

    祝愿前端越来越好。


    参考文献

    https://www.w3.org/html/logo/

    http://caniuse.com/

    展开全文
  • 前端HTML5十大新特性详细总结

    千次阅读 多人点赞 2021-04-04 21:22:03
    前端HTML5十大新特性总结 一 必须知道 写前端的都知道,在代码最前面都有这一行代码,大家都知道一定要把这东西写上去。 <!DOCTYPE html> 但是!这是什么玩意儿?为什么要写上去?不写上去会怎么样?很少人去...

    前端HTML5十大新特性总结

    一 必须知道

    写前端的都知道,在代码最前面都有这一行代码,大家都知道一定要把这东西写上去。

    <!DOCTYPE html>
    

    但是!这是什么玩意儿?为什么要写上去?不写上去会怎么样?很少人去注意到,反正就照写就可以了。

    所以,这是个啥玩意儿?
    这是声明!这是HTML5声明的新特性!

    既然有HTML5,那肯定有HTML4是吧,那HTML4是怎么声明的呢?

    HTML4有三种声明方式
    Strict(严格模式
    Transitional(过渡模式)
    Frameset(框架模式)
    具体是什么样的声明格式,有兴趣百度谷歌。(因为现在很少用了,所以我也懒得去记住了TT)

    HTML5很简单只需要统一声明
    声明有什么作用呢?
    它就是用来告诉浏览器文档使用哪一种HTML或者XHYML规范的。

    <!DOCTYPE html>
    

    那为什么可以这么用呢?

    百度给的解释:因为HTML5不是SGML的子集,从最开始的声明方式就不一样了。

    那么问题又来了,什么是SGML呢?一看就是某些英文单词的首字母拼凑在一起的是吧。

    那是什么呢?SGML是Standard Generalized Markup Language,标准通用标记语言。是一种很复杂的标记语言,从HTML,XML,衍生而来的。

    HTML5的新特性之声明就写到这吧。也理解了这一行必须写的代码是个啥玩意儿!

    二 HTML5十大新特性

    在这里插入图片描述

    2.1 语义标签

    什么是语义标签,我自己的理解就是看到标签我就能明白这是什么意思。以前制作网页布局基本使用div来做。div就是一个普通的块级标签,对搜索引擎来说没有任何的语义。
    btw面试前端的时候面试官可能会问你语义标签有哪一些?这平时都是记不住的,都是用到再去查的,所以面试的时候再去复习吧。
    HTML5新增的语义标签有以下这个几个,这几个很好记住,在理解的基础上记住。我是在纸上画出页面的大概布局,然后划分区域,填入该区域的标签,根据意思去填。比如头部,就是header对吧,很简单。

    Q:对整个HTML结构进行语义化的规范操作有什么好处?
    A:1 有利于SEO(Search Engine Optimization 搜索引擎优化),和搜索引擎建立良好的沟通,有助于爬虫爬取更多有效的信息。因为爬虫依赖于标签来确定上下文和各个关键字的权重。
    2 方便其他设备的解析(屏幕阅读器,移动设备),以有意义的方式来渲染网页。
    3 方便团队开发和维护,增加代码可读性,遵循标准,减少差异化。

    <!--header:网页的头部,作为一个网页内容快的标题-->
    <header></header>
    <!--nav:导航栏部分,定于整个页面的主要导航部分-->
    <nav></nav>
    <!--section:网页的一个内容区块-->
    <section></section>
    <!--aside:侧边栏,可以是相关链接或者资料-->
    <aside></aside>
    <!--artical:区块内的一个独立区域,定义自成一体独立的内容-->
    <artical></artical>
    <!--footer:网页的尾部,可以是作者,版权信息,附录等等-->
    <footer></footer>
    

    attention
    语义化标签主要是针对搜索引擎
    新标签可复用
    浏览器兼容问题,在IE9中(2021最新版),需要 转化为块级元素。

    header,nav,main{
        diaplay:block;
    }
    
    • 结构代码可以这么写
    /*结构代码*/
    <header>
    	<nav>导航栏</nav>
    </header>
    <section>
    	<aside>侧边栏</aside>
    	<article>独立内容块</article>
    </section>
    <footer>尾部</footer>
    
    /*还有一个<main>主题标签了解一下就可以了*/
    

    页面布局构图是这样的!
    网页布局清晰有条理,用户体验感也提升了不少。我们在浏览网页的时候都希望有一个清晰的逻辑和浏览顺序,容易catch到我们需要获取的信息。
    在这里插入图片描述

    2.2 增强型表单

    • 新的表单类型

    (1)邮箱验证

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>邮箱验证</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="email">
            <input type="submit">
        </form>
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    这个是新增的输入框类型,user在输入框填写后提交信息,自动验证email域的值是否合法有效

    (2)数值输入

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>数值输入</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="number" min="9" max="12">
            <!--限制输入的数值范围在9-12之间,包括9和12-->
            <input type="submit">
        </form>
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    这是新增的数值类型。输入的值不在区间范围内,会自动提示。

    (3)文件导入

    attention:上传本地文件,需js代码配合。如果需要上传多个文件,给表单添加mulitiple属性。如果上传图片,给表单添加enctype属性。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>文件导入</title>
        <style>
    
        </style>
    </head>
    <body>
        <form enctype="multipart/form-data">
            <input type="file" id="myFile" multiple>
            <input type="submit">
        </form>
        <img src="" id="myPhoto" alt="photo">
    </body>
    <!--js代码展示-->
    <script>
    	const myFile = document.getElementById('myFile')
    	const myPhoto = document.getElementById('myPhoto')
    	myFile.onchange = ()=>{
    		console.log(myFile.files)
    		const file = myFile.files[0]
    		const read = new FileReader()
    		//转译文件地址
    		read.readAsDataURL(file)
    		//文件加载完成就显示出来
    		read.onload = ()=>{
    			myPhoto.src = read.result
    		}
    	}
    </script>
    </html>
    

    (4)图片按钮

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>图片按钮</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="image" src="C:\Users\Gabrielle\Desktop\myPhoto.jpg" width=750 alt="myGimdong">
            <!--src里面填写的是我电脑的本地图片绝对路径,请添加你自己的本地图片的绝对路径或者相对路径-->
        </form>
    </body>
    </html>
    

    效果展示
    在这里插入图片描述

    (6)颜色选择

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>颜色选择</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="color">
            <input type="submit">
        </form>
          
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    选择调色板pick颜色,或者手动输入RGB的值,都可以选择颜色。

    (7)日期表示

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>日期表示</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="date">
            <!--日期选择出来date,还有datatime,datatime-local-->
            <input type="submit">
        </form>
          
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    (8)搜索框

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>搜索框</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="search" placeholder="我是输入字段为空时的提示信息">
            <input type="submit">
        </form>
          
    </body>
    </html>
    

    效果展示
    在这里插入图片描述

    (9)手机号码输入框(pc端没有特别明显的效果,主要用于手机移动端)

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>手机输入框</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="tel">
            <input type="submit">
        </form>   
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    (10)网址输入框

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>网址入框</title>
        <style>
    
        </style>
    </head>
    <body>
        <form>
            <input type="url">
            <input type="submit">
        </form>   
    </body>
    </html>
    

    效果展示

    在这里插入图片描述

    这个表单可以验证网址是否合法有效,必须为http格式。

    • 新的表单的新属性

    (1)placeholder

    这个属性是文本的占位符,相当于一种提示信息,显示在输入域,描述期待user输入的值。

    <input type="text" placeholder="请输入文字">
    

    (2)required

    这个属性的值为Bool,默认为true,意思是在输入域不能为空

    <input type="text" required>
    

    (3)autofocus

    auto是自动的意思,focus是聚焦的意思,这个属性描述的就是自动聚焦到需要填写的textarea。

    <input type="text" autofocus>
    

    (4)autocomplete

    这个属性有两个值,一个是on,另一个是off。默认是on,与email相反,email默认是off。功能是提示写过的信息。

    attention:这个属性一定要和name一起使用,不然是不合法不生效的。

    <input type="text" name="username" autocomplete>
    

    (5)minlength和maxlength

    这个属性限定输入的最少字数和最多字数,以字符个数计数。

    <input type="text" min="9" max="15">
    

    2.3视频和音频

    很多的视频都是通过插件(比如flash)来实现的,但并不是所有的浏览器都拥有相同的插件,为了能让视频和音频在网页内播放成功,HTML5规定了一种通过video,audio来包含视频播放的标准。

    • video----支持格式有ogg,MP3,webm
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>video标签</title>
        <style>
    
        </style>
    </head>
    <body>
       <video src="xxx.ogg"></video>
       <video src="xxx.mp4"></video>
       <!--可以嵌套多个video标签,用于表现同一个播放源的多种播放方式,第一个视频格式不支持的时候会轮到下一个标签,直到成功-->
       Sorry, your browser doesn't support video. Try another browser.
    </body>
    </html>
    

    video的方法,属性,事件可以使用js来控制。

    方法:play(),pause(),load(),分别是播放,停止,加载方法。

    属性:width,height,controls。width和height属性值为像素或者百分比,功能是设置播放窗口的宽度和高度。controls属性值为boolean,功能是控制播放条。

    控制:使用DOM

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>video</title>
        <style>
    
        </style>
    </head>
    <body>
        <div style="text-align: center;">
          <button onclick="playPause">play/pause</button>
          <button onclick="makeBigger">bigger</button>
          <button onclick="makeSmaller">smaller</button>
          <button onclick="makeNormal">normal</button>
        </div>
      <video id="myVideo" width="420">
          <source src="xxx.ogg">
          <source src="xxx.mp4">
        Sorry, your browser doesn't support video. Try another browser.
      </video>
    </body>
    <script>
        var myVideo = document.getElementById("myVideo");
    
        function playPause(){
            if(myVideo.paused)
            myVideo.play();
        }
    
        function makeBigger(){
            myVideo.width = 560;
        }
    
        function makeSmaller(){
            myVideo.width = 320;
        }
    
        function makeNormal(){
            myVideo.width = 420;
        }
    </script>
    </html>
    
    • audio----支持格式有ogg,Wav,mp3

    audio可以实现与flash相同的功能,比如回放,跳转缓冲等等。与video用法相似。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>audio标签</title>
        <style>
    
        </style>
    </head>
    <body>
       <audio controls>
           <source src="xxx.mp3">
           <source src="xxx.Wav">
       </audio>
       Sorry, your browser doesn't support audio. Try another browser.
    </body>
    </html>
    

    属性:autoplay:自动播放,值的类型为bool,默认为true。

    ​ controls:进度条控制,值的类型为bool。

    ​ loop:循环播放,值的类型为bool。

    ​ muted:静音播放,值的类型为bool。

    ​ poster:预加载图片在播放视频之前,值为图片路径URL。就是我们通常理解的视频封面。

    2.4 canvas绘图

    canvas的 html代码很简单,主要重点是js代码的编写。

    绘图步骤

    1 在html5页面中添加canvas元素,定义id方便js调用。

    <canvas id="myCanvas" width = 500 height = 200></canvas>
    

    2 在js代码中通过id获取

    var c = document.getElementById(myCanvas);
    

    3 通过getContext()的方法来获取上下文Context,创建context对象,获取2d绘制环境

    var context = c.getContext("2d");
    

    4 通过js脚本绘制,你喜欢画什么就画什么。

    2.5 SVG绘图

    这是使用xml描述2d图形的语言。

    那什么是xml呢?xml功能是传输和存储数据。

    那传输了存储了数据,我怎么看见它呢?是的,这就是html的功能了,用来显示数据,可视化给user。

    SVG绘图和canvas绘图都是用来画图,那有什么区别呢?

    SVG比canvas绘图好用,SVG不容易失帧,就是更稳定的意思。SVG对前端程序员更友好一点,它比较容易编辑,只需要从描述中移除元素就可以了。

    • circle画圆(举个栗子)
    <svg version="相关版本号,比如1.1">
          <circle cx = "100" cy = "50"stroke="red" stroke-width="5" fill="black"/>
          <!--
    			cx:圆心的(x轴)横坐标
    			cy:圆心的(y轴)纵坐标
    			r:圆心的半径
    			stroke:外边线条的颜色
    			stroke-width:外边线条的宽度
    			fill:圆填充的颜色
    	  -->
    </svg>
    

    2.6 地理位置

    地理位置能够识别你的定位,并且与别人共享地理信息。那么怎么获取地理位置信息呢?

    获取地理位置的方法?

    1 通过ip地址

    2 电脑上的位置信息定位

    • 利用基站获取网络位置,只能获取大致位置,不够精确。
    • 通过卫星定位获取经纬度信息的GPS设备,误差很小,位置精准。但GPS开启定位有延迟。

    attention:浏览器必须在用户允许情况下才可以发送用户的位置信息给服务器。

    地理位置API

    Q:什么是API?

    A:API是Application Programming Interface,即应用程序接口,是预先定义的接口(函数,http接口)

    (1)调用位置函数

    function get_location() {
      navigator.geolocation.getCurrentPosition(show_map, handle_error, PositionOptions);
    }//这段js代码功能是触发浏览器弹出信息条,询问user是否分享地理位置。
    //show_map是获取位置信息成功的回调函数
    //handle_error是获取位置信息失败的回调函数
    //PositionOptions是获取地理位置的设置对象
    

    (2)show_map获取地理位置

    function show_map(position) {
      var latitude = position.coords.latitude;//获取纬度
      var longitude = position.coords.longitude;//获取经度
    }//回调函数要传入position对象
    //position 对象的属性:
    //coords.latitude 纬度,度
    //coords.longtitude 经度,度
    //coords.altitude 海拔,米
    //coords.accuracy 精确度,米
    //coords.altitudeAccuracy 海拔精确度,米
    // coords.heading 方向,度,顺时针,以正北为基准
    //coords.speed 速度,米/秒
    //timestamp 时间戳,类似 Date() 对象
    //这些属性会因为用户的设备和后台定位的服务器不同而出现属性值为null
    

    (3)handle_error容错处理

    function handle_error(e) {
      switch(e.code)  {//code错误类型
        case e.PERMISSION_DENIED:
          //用户拒绝对获取地理位置的请求。
              //user点击不共享或者拒绝位置共享
          break;
        case e.POSITION_UNAVAILABLE:
          //位置信息是不可用的。
              //网络不可用或者无法连接到获取位置信息的卫星
          break;
        case e.TIMEOUT:
          //请求用户地理位置超时。
              //网络可用但是计算超时间
          break;
        case e.UNKNOWN_ERROR:
          //未知错误。
          break;
      }
    }
    

    (4)PositionOptions 对象设置

    navigator.geolocation.getCurrentPosition(show_map, handle_error, {enableHighAccuracy: true,timeoout: 170000, maximumAge: 87000})
    //enableHighAccuracy 开启高精度定位,默认 false
    //timeout字面意思,网络请求超时
    //maximumAge允许user将一定时间内缓存的位置信息快速返回给Web应用,默认值0ms
    

    (5)watchPosition() 持续获取

    定位检测用户位置的更改,设备自己会找寻一个最佳的时间间隔,定时更改位置信息。

    var watch = navigator.geolocation.watchPosition(show_map, handle_error, {enableHighAccuracy: true,timeoout: 170000, maximumAge: 87000})
    clearWatch(watch);//这个方法用于停止监测user位置信息的更改。
    

    2.7 拖放API

    1 设置元素为可拖放

    一般情况下,一个元素的默认拖拽属性为false。想要在页面拖拽元素,就要把属性这是为true

    <img draggable = "true">
    

    2 拖放什么? 用setData()或者ondragstart。

    现在允许拖放了,那么拖拽什么?拖拽的时候会发生什么,触发什么事件?

    function drag (event){
            event.dataTransfer.setData("Text",event.target.id);
    }//dataTransfer.setData() 方法设置被拖数据的数据类型和值:
    

    3 放置元素

    现在拖放出来了,你要把元素安置到哪里去呢?这是一个问题。一般默认不能把元素放置其他元素中,如果需要,必须要对元素的默认方式进行处理。那要怎么办呢?

    event.preventDefault()
    //通过调用 ondragover 事件的event.preventDefault()方法:
    

    4 进行放置

    现在放置到哪里我们处理了,但是缺乏一个动作事件。当放置被拖数据时,会发生 drop 事件。ondrop 属性调用了一个函数,drop(event)。

    function drop(event)        
    {        
    event.preventDefault();        
    var data=event.dataTransfer.getData("Text");        
    event.target.appendChild(document.getElementById(data));        
    }
    //preventDefault()避免浏览器对数据的默认处理,drop事件的默认行为是以连接的形式打开
    //dataTransfer.getData("Text")获取拖拽的数据,该方法将返回在setData()方法中设置为相同类型的任何数据
    

    attention:拖拽是一个重点,需要熟练。

    data Transfer。getData()只在ondrop中可以用

    // 元素放置目标区域,进入目标区域触发 ondragenter 事件
    ondragenter()
    
    // 进入目标区域后触发 ondragover 事件,会一直响应over事件不会触发ondrag
    ondragover = function(event) {
        event.preventDefault();
    }
    
    // 元素放置目标区域,离开目标区域触发 ondragleave 事件
    ondragleave()
    
    // 元素放置目标区域,鼠标弹起触发 ondrop 事件
    ondrop = function(event) {
        // 从开始触发时 dataTransfer.setData() 获取储存的数据
        // 获取dataTransfer.getData() 其他回调事件无法获取 getData()
        this.append(document.getElementById(event.dataTransfer.getData('xxx')));
    }
    

    拖拽目标对象的方法

    1. setData(format,data)
    2. getData(format)
    3. clearData([format])
    4. addElement(element)
    5. setDragImage(element,x,y)
    • setData(format,data)

    将指定格式的数据赋值给dataTransfer对象,参数format定义数据的格式也就是数据的类型,data为待赋值的数据

    • getData(format)

    从dataTransfer对象中获取指定格式的数据,format代表数据格式,data为数据。

    • clearData([format])

    从dataTransfer对象中删除指定格式的数据,参数可选,若不给出,则为删除对象中所有的数据

    • addElement(element)

    添加自定义图标

    • setDragImage(element,x,y)

    设置拖放操作的自定义图标。其中element设置自定义图标,x设置图标与鼠标在水平方向上的距离,y设置图标与鼠标在垂直方向上的距离。

    拖拽属性值

    none:不能把拖动的元素放在这里。这是除了文本框之外所有元素默认的值。
    move:把拖动的元素移动到放置目标。
    copy:把拖动的元素复制到放置目标。
    link:放置目标会打开拖动的元素(但拖动的元素必须是个链接URL地址)。

    拖拽的node
    定义三个变量
    1 当前拖拽的node
    2 拖拽时经过的node
    3 最终放置的node

    敲黑板,后面这个三个新特性是重点!!!!!

    2.8 Web Worker

    web worker 是运行在后台的 JavaScript。
    Q1:JS是怎么执行的?
    A1:JS是单线程执行模式。

    Q2:什么是单线程模式?
    A2:所有任务只能在一个线程上执行,一次只做一件事情。前面的没有执行完,后面的只能等待。

    Q3:有什么不好的地方吗?
    A3:1 现在的CPU大多数是多核的,计算能力牛逼到不行。单线程无法发挥出CPU计算的价值。
    2 页面上JS在执行的时候会阻塞浏览器的响应,影响用户体验。毕竟页面是为用户服务的。

    Q4:Web Worker解决了什么问题?
    A4:为js创建多线程环境。js在主线程执行,new一个子线程在后台执行。worker完成计算的任务返回给主线程,UI交互流畅,不会被阻塞。主线程中的代码执行会导致浏览器响应阻塞,而子线程代码执行不会。主线程和子线程两者互补干扰,独立执行。

    attention:操作web worker之前最重要的是检测浏览器是否支持。现在主流的浏览器对Web Worker兼容性并不高,比如Safari,更不用说IE浏览器了。但是这并不代表它没用。

     if(typeof(Worker)!=="undefined")
       {
       // yes
       }
     else
       {
       // no
       } 
    

    创建web worker文件

     var i=0;
     function timedCount()
     {
         i=i+1;
         postMessage(i);
         setTimeout("timedCount()",600);
     } 
     timedCount(); 
     //计数器
    

    创建web worker对象

    上一步已经创建了一个web worker文件,现在需要在html页面调用它。

    1 先检测文件是否存在

     if(typeof(w)=="undefined")
       {
       w=new Worker("myworkers.js");
       }
    

    2 然后我们就可以从 web worker 发送和接收消息了。向 web worker 添加一个 “onmessage” 事件监听器。

     w.onmessage=function(event){
     document.getElementById("result").innerHTML=event.data;
     }; 
    

    3 终止web worker

    当我们创建 web worker 对象后,它会持续监听消息(即使在外部脚本完成之后)直到其被终止为止。如需终止 web worker,并释放浏览器/计算机资源,可以用terminate() 方法。

     worker.terminate(); 
    

    Web Worker有五个限制
    (1)同源限制:分配给Worker线程运行的脚本文件,必须与主线程的脚本文件同源。
    (2)DOM限制:worker只能读取navigator对象和location对象,无法使用window,document,parent对象。因为woker线程所在的全局对象与主线程的不一样,所以也无法读取主线程所在页面的DOM对象。
    (3)通信联系:主线程和子线程无法直接通信,因为它们不在同一个上下环境。
    (4)脚本限制:woker线程不能执行alert()方法和confirm()方法,但可以使用XMLHttpRequst对象发出AJAX请求。
    Q1:什么是XMLHttpRequst对象?
    A1:用户在后台和服务器交换数据的对象。

    Q2:功能是什么?
    A2:不重新加载页面的情况下更新页面;在页面加载后从服务器请求数据和接收数据;在后台向服务器发送数据。

    (5)文件限制:worker线程不能读取本地文件(file://),加载的脚本必须来源于网络。

    2.9 Web Storage

    看到stoage就可以猜测到这个是存储,那是什么东西的存储呢。当然是数据的存储。这些数据可以是临时的也可以是永久的。

    Q1:它什么要出现,相比HTML4它优势是什么?
    A1:HTML4中用cookie,在用户端保存用户数据。但是存在弊端。内存大小不够大只有4kb;浪费带宽,因为数据发送的时候是连HTTP事务一起发送,造成资源浪费;操作cookie复杂麻烦困难。所以HTML5用Web Storage在客户端本地保存用户数据。

    Q2:cookie和Web Storage有什么区别?
    A2:Web Storage存储的空间大小更大,一般有5MB;用户数据存储在本地(浏览器)不与服务器发生通信;Web Storage本身自带方法setletm(),getletm(),removeletm(),clean()等,不需要cookie复杂的封装setCookie,getCookie。操作简单。

    web Storage分类
    1 localStorage
    2 sessionStorage

    Q1:什么是sessiionStorge?
    A1:user进入页面浏览至关闭浏览器的时间。页面在,数据在,页面无,数据无。重新加载页面的时候,数据仍然存在。

    Q2:localStorage和sessionStorage有什么区别?
    A2:相同点
    (1)数据都保存在浏览器客户端
    (2)同源,即同域名,同端口,同协议。
    (3)操作方法相同。
    不同点
    (1)生命周期不同。localStorage是永久保存,除非用户手动清除数据。sessionStorage是临时保存。
    (2)作用域不同。浏览器有很多种,所以无法共享用户数据,也就是不同源的页面无法共享数据。localStorage信息可以在相同浏览器中同源的不同页面,不同标签,不同窗口中共用。sessionStorage不可以在不同页面,不同标签,不同窗口中共用,即使是同源。

    • 特点

    值可以是任意的数据类型,只要是key/value形式可以保存的。 数据将永不过期,除非用户明确调用了delete()方法,或者浏览器限制了空间大小,或者其他原因(比如用户清空历史数据)数据项在整个domain(域名)内都可见。

    • 方法

    setItem(key,value): 添加一个键值对,存储
    sessionStorage(会话存储)对象
    getItem(key): 根据key获取值
    clear(): 清空sessionStorage(会话存储)的所有键/值对
    removeItem(key): 从sessionStorage 移除某个项(键值对)
    key(n): 获取第n个key。

    • key/value

    有两种方式可以把值存储到sessionStoage

    // 第一种方式,标准方法
    sessionStorage.setItem('email','xxx@qq.com');
    // 第二种方式,直接当成普通对象属性赋值。
    sessionStorage.blog = 'http://xxxxxx';
    
    • 两种获取值的方法
    // 1. 标准方法
    var email = sessionStorage.getItem('email');
    // 2. 直接取属性值
    var blog = sessionStorage.blog;
    
    • 移除key/value
    // 移除之后,再获取值,将会得到 undefined
    // 根据key,移除键值对
    sessionStorage.removeItem('email');
    
    • 清空sessionStorage
    // 全部清除
    sessionStorage.clear();
    

    2.10 Web Socket

    要理解这个新特性,需要有一些网络基础的知识。w3cschool对其总结很到位,所以我直接照搬过来了。WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

    API 用于创建 WebSocket 对象。

    var Socket = new WebSocket(url, [protocal] );
    //第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。
    
    • WebSocket属性

    Socket.readyState

    0:表示连接尚未建立

    1:表示连接已经建立,可以进行通信

    2:表示连接正在进行关闭

    3:表示连接已经关闭或者连接不能打开

    • WebSocket事件

    open:连接建立时触发

    message:客户端接收服务端数据时触发

    error:通信发生错误时触发

    close:连接关闭时触发

    • WebSocket方法

    Socket.send():使用连接发送数据

    Socket.close():关闭连接

    代码展示示例

    <!DOCTYPE HTML>
    <html>
       <head>
       <meta charset="utf-8">
       <title>webscoket</title>
    	
          <script type="text/javascript">
             function WebSocketTest()
             {
                if ("WebSocket" in window)
                {
                   alert("您的浏览器支持 WebSocket!");
                   
                   // 打开一个 web socket
                   var ws = new WebSocket("ws://localhost:xxxx/echo");
    				
                   ws.onopen = function()
                   {
                      // Web Socket 已连接上,使用 send() 方法发送数据
                      ws.send("发送数据");
                      alert("数据发送中...");
                   };
    				
                   ws.onmessage = function (evt) 
                   { 
                      var received_msg = evt.data;
                      alert("数据已接收...");
                   };
    				
                   ws.onclose = function()
                   { 
                      // 关闭 websocket
                      alert("连接已关闭..."); 
                   };
                }
                
                else
                {
                   // 浏览器不支持 WebSocket
                   alert("您的浏览器不支持 WebSocket!");
                }
             }
          </script>
    		
       </head>
       <body>
       
          <div id="sse">
             <a href="javascript:WebSocketTest()">运行 WebSocket</a>
          </div>
          
       </body>
    </html>
    
    三 总结

    HTML5的十大新特性是需要掌握的,在前端面试中很频繁的被问到,重点要理解Web Worker,Web Storage,Web Socket。重要的不是背诵,而是去理解。一个新事物取代一个旧事物肯定是为了更好,所以是更好的什么呢?一般来讲,人都是很懒的生物,更好的用户体验,更好的操作简单,更好的代码可读性等等,从这几个方面去思考为什么HTML5需要出现,它的出现解决了什么问题?相比HTML4有什么优势?改进了什么?优化了什么功能?与HTML4有什么区别?想清楚这些问题,基本也就可以在理解的基础上去掌握这些知识点。

    展开全文
  • HTML5新特性

    万次阅读 2012-02-09 16:46:46
    · 不是所有的浏览器都支持HTML5,所以在资源元素的下面,可以提供一个下载链接或者嵌入视频的flash版本替代,这取决于个人。 · 如果想要所有的浏览器都支持HTML5标签,只要链接一个js文件就可以。在页面的...
  • HTML5新特性。兼容性:HTML5归根结底也是HTML的一个版本,它不是颠覆性的革新,而是兼容之前版本。 合理性:新增的标签等,不是随意的构造的,而是根据使用大数据分析用户习惯,为用户提供便利而开发的。例如方便...
  • HTML5新特性之离线缓存技术

    万次阅读 2016-04-12 16:34:32
    HTML5之前的网页,都是无连接,必须联网才能访问,这其实也是web的特色,这其实对于PC是时代问题并不大,但到了移动互联网时代,设备终端位置不再固定, 依赖无线信号,网络的可靠性变得降低,比如坐在火车上,过了...
  • HTML5新特性

    千次阅读 2018-06-28 19:43:37
    HTML5现在已经不是SGML(标准通用置标语言)的子集,主要是关于图像,位置,存储,多任务等功能的增加。绘画canvas用于媒介回放的video和audio元素本地离线存储localStorage长期存储数据,浏览器关闭后数据不丢失...
  • HTML5新特性:FileReader 和 FormData

    万次阅读 2017-09-04 13:34:19
    其中我用到了两个HTML5新特性:FileReader和FormData; 首先介绍下这两个方法: HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取文件...
  • HTML5有哪些新特性

    千次阅读 2019-03-14 23:55:34
     IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签,浏览器支持标签后,还需要添加标签默认的样式。  可直接使用成熟的框架、比如html5shiv  <!--[if...
  • html5有哪些新特性,移除了那些元素?如何处理html5新标签的浏览器兼容问题 article;IE7/。 2,还新增了以下的几大类元素,利用这一特性让这些浏览器支持HTML5新标签,tt、header。 如何处理HTML5新标签的浏览器...
  • HTML5十个新特性

    万次阅读 多人点赞 2018-07-17 16:17:23
    :尚不是H5标准技术,基于HTML5 Canvas提供硬件3D加速渲染;有一个非常强大3D扩展库:three.js (四)Canvas绘图   H5原生技术,基于网页画布2D位图绘图技术,善于表现细腻颜色,可用于统计图表、页面...
  • 学习心得随记——阿西河前端教程——HTML的面试题——HTML5 有哪些新特性——声明方式
  • HTML5新特性之History

    千次阅读 2015-04-23 23:21:17
    几年前,Ajax的兴起给互联网带来了的生机,同时也使用户体验有了质的飞跃,用户无需刷新页面即可获取的数据,而页面也以一种更具有交互性的形式为用户展现视图,可以说这种变化对互联网发展的贡献是史无前例的。...
  • 学习心得随记——阿西河前端教程——HTML的面试题——HTML5 有哪些新特性——语义化标签
  • 这里由于不是本文的主要内容,所以就不详细介绍HTML5表单新特性,需要了解和学习的介意查看本人的另外一篇文章,里面有很详细的介绍关于HTML5的表单的新特性。 网址: ...
  • 一种方式是用navigator.userAgent或navigator.appName来检测浏览器类型和版本,不过这种方式不是很可靠,浏览器对于一些新特性也是在逐渐支持,不能肯定说某个浏览器100%支持了HTML5。而且,IE11做了一个恶心的举动...
  • HTML5和CSS3新特性一览

    万次阅读 多人点赞 2017-04-04 20:53:05
    HTML5提供了的元素来创建更好的页面结构: 标签 描述 定义页面独立的内容区域。 定义页面的侧边栏内容。 允许您设置一段文本,使其脱离其父元素的文本方向设置。 定义命令按钮...
  • 使用Modernizr探测HTML5/CSS3新特性

    千次阅读 2012-09-18 14:53:03
    HTML5, CSS3以及相关技术(例如canvas和web sockets)带来了非常有用的特性,可以让我们的web程序提升一个的level。这些技术允许我们只用HTML,CSS和JavaScript就可以构建包括在平板和移动设备上能够运行的多样化...
  • H5新特性

    千次阅读 2016-12-07 14:36:37
    1. 的Doctype  尽管使用,即使浏览器不懂这句话也会按照标准模式去渲染  2. Figure元素  用和来语义化地表示带标题的图片  figure>  img src=”path/to/image” alt=”About image” />  figcaption>  ...
  • HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。 (1)绘画 canvas; (2)用于媒介回放的 video 和 audio 元素; (3)本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不...
  • CSS3 渐变新特性HTML5 Canvas画布背景渐变实现方法详解 大家好,又见面了,感觉我上一篇博客对部分同学都挺有帮助的,于是我决定继续写下去,会继续的解析知识点让大家更容易理解,希望能给大家带来帮助,愿意一起...
  • HTML5 history新特性pushState、replaceState

    万次阅读 2012-04-04 21:49:49
    HTML5开始,我们可以开始操作这个历史记录堆栈。   1.History 使用back(),forward(),和go()方法可以在用户的历史记录中前进和后退 前进和后退 后退: window.history.back(); 这个方法会像用户点击了
  • *HTML5 现在已经不是SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。 *绘画canvas   用于媒介回放的video 和audio 元素  本地离线存储localStorage 长期存储数据,浏览器关闭后数据不丢失; ...
  • Hibernate5总结及新特性

    千次阅读 2017-06-09 14:13:35
    5. 明确调用Hibernate程度时,session的方法必须在事务之内执行, 因为session是操作缓存中的数据,只有提交了事务之后,缓存中的数据才能写到数据库中 。 6. 明确Hibernate对单表的增删改查操作,注意查询的时候...
  • 1. 的Doctype  尽管使用,即使浏览器不懂这句话也会按照标准模式去渲染  2. Figure元素  用和来语义化地表示带标题的图片        This is an image of something interesting.     3. 重新...
  • H5的新特性及部分API详解

    万次阅读 2016-08-09 19:19:04
    h5新特性总览移除的元素**纯表现的元素:**basefont、big、center、font等 **对可用性产生负面影响的元素:**frame、frameset、noframes新增的API语义:能够让你更恰当地描述你的内容是什么。 连通性:能够让你和...
  • Java 13 来袭,最新最全新特性解读

    万次阅读 多人点赞 2019-09-16 09:40:51
    2017年8月,JCP执行委员会提出将Java的发布频率改为每六个月一次,的发布周期严格遵循时间点,将在每年的3月份和9月份发布。 目前,JDK官网上已经可以看到JDK 13的进展,最新版的JDK 13将于2019年9月17日发布。 ...
  • 从JAVA5到JAVA10新特性总结

    千次阅读 多人点赞 2018-04-01 16:08:08
    JDK5新特性 1:自动装箱与拆箱: 自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装类中。 自动拆箱的过程:每当需要一个值时,被包装对象中的值就被自动地提取出来,没...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 394,924
精华内容 157,969
关键字:

哪个不是html5的新特性