h5新特性总览

移除的元素

纯表现的元素: basefont、big、center、font等 
对可用性产生负面影响的元素: frame、frameset、noframes

新增的API

语义: 能够让你更恰当地描述你的内容是什么。 
连通性: 能够让你和服务器之间通过创新的新技术方法进行通信(web sockets等)。 
离线 & 存储:能够让网页在客户端本地存储数据以及更高效地离线运行(离线资源、在线和离线事件、DOM存储、IndexDB、自web应用程序中使用文件[FileReader])。 
多媒体:使 video 和 audio 成为了在所有 Web 中的一等公民。 
2D/3D 绘图 & 效果:提供了一个更加分化范围的呈现选择(canvas、webGL)。 
性能 & 集成:提供了非常显著的性能优化和更有效的计算机硬件使用(WebWorkers、XMLHttpRequest2、HistoryAPI、拖放、requestAnimationFrame、全屏API、指针锁定API、在线和离线事件)。 
设备访问 Device Access:能够处理各种输入和输出设备(触控事件touch、使用地理位置定位、检测设备方向)。

部分API详述

由于篇幅较长,可以选择感兴趣的部分阅读 
存储机制 
File API 
Web Worker 
history对象 
2D绘图(canvas和svg) 
H5的兼容性

web存储机制

Web Storage的目的是克服由cookie带来的一些限制,当数据需要被严格控制在客户端上时,无需持续地将数据发回服务器。Web Storage的两个主要目标是:提供一种在cookie之外存储会话数据的途径;提供一种存储大量可以跨会话存在的数据机制。最初的Web Storage规范包含了两种对象的定义:sessionStorage和globalStorage。这两个对象在支持的浏览器中都是以windows对象属性的形式存在的。

sessionStorage对象

sessionStorage对象存储特定于某个会话的数据,也就是该数据只保持到浏览器关闭。这个对象就像会话cookie,也会在浏览器关闭后消失。存储在sessionStorage中的数据可以跨越页面刷新而存在,同时如果浏览器支持,浏览器崩溃并重启之后依然可用(FireFox和WebKit都支持,IE不支持) 
因为sessionStorage对象绑定于某个服务器会话,所以当文件在本地运行的时候是不可用的,存储在sessionStorage中的数据只能由最初给对象存储数据的野蛮访问到,所以对多页面应用有限制。 
sessionStorage对象可以使用setItem()或者直接设置新的属性来存储数据

//使用sessionStorage方法存储数据
sessionStorage.setitem('name','Nicholas');
//使用属性存储数据
sessionStorage.book = 'Profession JavaScript';
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

不同浏览器写入数据方面略有不同。FireFox和WebKit实现了同步写入,所以添加到存储空间中的数据时立刻被提交的。而IE的实现则是异步写入数据,所以在设置数据和将数据实际写入磁盘之间可能有一些延迟。对于少量数据而言,这个差异是可以忽略的。对于大量数据,IE要比其他浏览器更快的恢复执行,因为它会跳过实际的磁盘写入过程 
在IE8中可以强制把数据写入磁盘:在设置新数据之前使用begin()方法,并且在所有设置完成后调用commit()方法

sessionStorage.begin();//确保在这段代码执行的时候不会发生其他磁盘写入操作
sessionStorage.setitem('name','Nicholas');
sessionStorage.book = 'Profession JavaScript';
sessionStorage.commit();
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

sessionStorage中有数据时,可以使用getItem()或者通过直接访问属性名来获取数据。

//使用方法读取数据
var name = sessionStorage.getItem('name');
//使用属性读取数据
var book = sessionStorage.book;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

还可以通过结合length属性和key()方法来迭代sessionStorage的值。

for(var i = 0,len = sessionStorage.length; i < len; i++){var key = sessionStorage.key(i);var value = sessionStorage.getItem(key);alert(key + "=" + value);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

要从sessionStorage中删除数据可以使用delete操作符删除对象属性,也可以调用removeItem()方法。

delete sessionStorage.name;
sessionStorge.removeItem('book');
  • 1
  • 2
  • 1
  • 2

globalStorage对象

sessionStorage对象应该主要用于针对会话的小段数据的存储。如果需要跨越花花存储数据,那么globalStorage或者localStorage更为合适 
要使用globalStorage,首先要制定哪些域可以访问该数据。可以通过方括号标记使用属性来实现。

//保存数据
globalStorage['wrox.com'].name = 'Nicholas';
//获取数据
var name = globalStorage['wrox.com].name;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在这里,访问的是针对域名wrox.com的存储空间。这个存储空间对于wrox.com及其所有子域都是可以访问的。 
对globalStorage空间的访问,是依据发起请求的页面的域名、协议和端口来限制的(类似于ajax请求的同源策略)。如果实现不能确定域名,那么使用location.host作为属性名比较安全

globalStorage[location.host].name = 'Nicholas';
var book = globalStorage[location.host].getItem('book');
  • 1
  • 2
  • 1
  • 2

如果不使用removeItem()或者delete删除,或者用户为清除浏览器缓存,存储在globalStorage属性中的数据会一直保留在磁盘上。这让globalStorage非常适合在客户端存储文档或者长期保存用户偏好设置

localStorage对象

localStorage对象在修订过的HTML5规范中作为持久保存客户端数据的方案取代了globalStorage。与globalStorage不同,不能给localStorage指定任何访问规则;规则实现就设定好了。要访问同一个localStorage对象,页面必须来自同一个域名,使用同一种协议,在同一个端口上。这相当于globalStorage[location.host] 
由于localStorage是Storage的实例,所以可以像使用sessionStorage一样来使用它。

//使用方法存储数据
localStorage.setItem('name','Nichoalas');
//使用属性存储数据
localStorage.book = 'Professional JavaScript';
//使用方法读取数据
var name = localStorage.getItem('name')
//使用属性读取数据
var book = localStorage.book;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

存储在localStorage中的数据和存储在globalStorage中的数据一样,都遵循相同的规则:数据保留到通过JavaScript 
删除或者是用户清除浏览器缓存

File API

File API在表单中的文件输入字段的基础上,又添加了一些直接访问文件信息的接口。H5在DOM中为文件输入元素添加了一个files集合,在通过文本输入字段选择了一或多个文件时,files集合中将包含一组File对象,每个File对象对应着一个文件。每个File对象都有下列只读属性

  • name: 本地文件系统的文件名
  • size: 文件的字节大小
  • type:字符串,文件的MIME类型。
  • lastModifiedDate:字符串,文件上一次被修改的事件(只有chrome实现了这个属性)

现在我们获取id为‘files-list’的input为file的元素,将该元素中上传的文件输出到控制台

var filesList = document.getElementById('files-list');EventUtil.addHandler(filesList,'change',funciton(e){var files = EventUtil.getTarget(e).files,i = 0,len = files.length;while(i<len){console.log(files[i].name + '('+files[i].type+','+files[i].size +'bytes)');i++;}})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

FileReader类型

FlieReader类型实现的是一种异步文件读取机制。可以把FileReader想象成XMLHttpRequest,区别只是它读取的是文件心痛,而不是远程服务器。为了读取文件中的数据,FileReader提供了如下几个方法:

  • readAsText(file, encoding):以纯文本的形式读取文件,将读取到的文本保存在result属性中。
  • readAsDataURL(file):读取文件并将文件一数据URI的形式保存在result属性中
  • readAsBinaryString(file)(已废弃):读取文件并将一个字符串保存在result属性中,字符串中的每一个字符表示一字节
  • readAsArrayBuffer(file):读取文件并将一个包含文件内容的ArrayBuffer保存在result属性中。

由于读取过程是异步的,因此FileReader也提供了几个事件。其中最有用的三个事件是progress、error和load,分别表示是否又读取了新数据,是否发生了错误以及是否读完了整个文件。

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList, "change", function(event){var info = "",output = document.getElementById("output"),progress = document.getElementById("progress"),files = EventUtil.getTarget(event).files,type = "default",reader = new FileReader();if (/image/.test(files[0].type)){reader.readAsDataURL(files[0]);type = "image";} else {reader.readAsText(files[0]);type = "text";}reader.onerror = function(){output.innerHTML = "Could not read file, error code is " + reader.error.code;};reader.onprogress = function(event){if (event.lengthComputable){progress.innerHTML = event.loaded + "/" + event.total;}};reader.onload = function(){var html = "";switch(type){case "image":html = "<img src=\"" + reader.result + "\">";break;case "text":html = reader.result;break;}output.innerHTML = html;};
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

读取部分内容

File对象支持一个slice()方法以实现读取文件的一部分而不是全部内容,这个方法在FireFox中的实现叫mozSlice(),在chrome中的实现是webkitSlice(),Safiri的5.1及之前的版本不支持这个方法。Slice()方法接收两个参数:起始字节及要读取的字节数。这个方法返回一个Blob实例,Blob是File类型的父类型。下面是一个通用的函数,可以在不同实践中使用slice()方法:

function blobSlice(blob,startByte,length){if(blob.slice){return blob.slice(startByte,length);} else if(blob.webkitSlice){return blob.webkitSlice(startByte,length);} else if(blob.webkitSlice){return blob.webkitSlice(startByte,length);} else {return null;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

blob类型有一个size属性和一个type属性,而且它也支持slice()方法,以便进一步切割数据。通过FileReader也可以从Blob中读取数据。下面这个例子只读取文件的32B内容

var filesList = document.getElementById('files-list');
EventUtil.addHandler(filesList, "change", function(event){var info = "",output = document.getElementById("output"),progress = document.getElementById("progress"),files = EventUtil.getTarget(event).files,type = "default",reader = new FileReader();blob = blobSlice(files[0],0,32);if (blob){reader.readAsText(blob);reader.onerror = function(){outpit.innerHTML = 'could not read file,error code is' + reader.error.code;}reader.onload = function(){output.innerHTML = reader.result;};} else {alert('your browser does not support slice()');}reader.onerror = function(){output.innerHTML = "Could not read file, error code is " + reader.error.code;};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

只读取文件的一部分可以节省时间,非常适合只关注数据中某个特定部分(如请求头部)的情况

对象URL

对象URL也被称为blob URL,指的是引用保存在File或Blob中数据的URL。使用对象URL的好处是可以不必把文件内容读取到JavaScript中而直接使用文件内容。为此,只要在需要文件内容的地方提供对象URL即可。要创建对象URL,可以使用window.URL.createObjectURL()方法,并传入File或Blob对象。这个方法在Chrome中的实现叫window.webkitURL.createObjectURL(),因此可以通过如下函数来消除命名的差异:

function createObjectURL(blob){if(window.URL){return window.URL.createObjectURL(blob);} else if (window.webkitURL) {return window.webkitURL.createObjectURL(blob);} else {return null;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这个函数的返回值是一个字符串,指向一块内存的地址。因为这个字符串是URL,所以在DOM中也能使用。例如,以下代码可以在页面中显示一个图像文件:

var filesList = document.getElementById("files-list");
EventUtil.addHandler(filesList, "change", function(event){var info = "",output = document.getElementById("output"),progress = document.getElementById("progress"),files = EventUtil.getTarget(event).files,type = "default",reader = new FileReader();url = createObjectURL(files[0]);if(url) {if (/image/.test(files[0].type)){output.innerHTML="<img src =\"" + url + "\">"} else {output.innerHTML = 'not an image';}} else {output.innerHTML = "your browser doesn't support object URLs";}
});reader.onerror = function(){output.innerHTML = "Could not read file, error code is " + reader.error.code;};reader.onprogress = function(event){if (event.lengthComputable){progress.innerHTML = event.loaded + "/" + event.total;}};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

读取拖放的文件

围绕读取文件信息,结合使用Html5拖放API和文件API,能够创造出令人瞩目的用户界面:在页面上创建了自定义的放置目标后,可以从桌面上把文件拖放到该目标。与拖放一张图片或者一个链接类似,从桌面上把文件拖放到浏览器中也会触发drop事件。而且可以在e.dataTransfer.files中读到被放置的文件,当然此时它是一个File对象,与童年过文件输入字段取得的File对象一样。

var droptarget = document.getElementById('droptarget');function handleEvent(e){var info = '';var output = document.getElementById('output');var files, i, len;e.preventDefault();if(e.type == 'drop') {files = e.dataTransfer.files;i = 0;len = files.length;while(i < len){info += files[i].name + '(' + files[i].type + ',' + files[i].size + 'bytes<br>';i++;}output.innerHTML = info;}
}
droptarget.addHandler('dragenter',handleEvent,false);
droptarget.addHandler('drageover',handleEvent,false);
droptarget.addHandler('drop',handleEvent,false);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Web Workers

专用Web Worker提供可一个简单的方法使的web内容能够在后台运行脚本。一旦worker创建后,它可以向由它的创建者指定的事件监听函数传递消息,这样改worker生成的所有任务就都会接收到这个消息。worker线程能够在不干扰UI的情况下执行任务。

生成worker

创建一个新的worker十分简单。就是调用Worker()构造函数,指定一个要在worker线程内运行的脚本的URI,如果希望能够收到worker的通知,可以将worker的onmessage属性设置成一个特定的事件处理函数,如果希望能够发送信息到worker,可以使用postmessage方法

var myWorker = new Worker("my_task.js");myWorker.onmessage = function (oEvent) {console.log("Called back by the worker!\n");
};myWorker.postMessage(""); // start the worker.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

传递数据

在主页面与worker之间传递的数据是通过拷贝,而不是共享来完成的。传递给worker的对象需要经过序列化,接下来在另一端还需要反序列化。页面与worker不会共享同一个实例,最终的结果就是在每次通信结束时生成了数据的一个副本。大部分浏览器使用结构化拷贝来实现该特性。 
example.html(主页面)

var myWorker = new Worker("my_task.js");myWorker.onmessage = function (oEvent) {console.log("Worker said : " + oEvent.data);
};myWorker.postMessage("ali");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

my_task.js(worker)

postMessage("I\'m working before postMessage(\'ali\').");onmessage = function (oEvent) {postMessage("Hi " + oEvent.data);
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

Worker全局作用域

关于Web Worker,最重要的是要知道它所执行的JavaScript代码完全在另一个作用域,与当前网页中的代码不共享作用域。在Web Worker中,同样有一个全局对象和其他对象以及方法。但是Web Worker中的代码不能访问DOM,也无法通过任何方式影响页面的外观 
Web Worker中的全局对象是worker对象本身。也就是说,在这个特殊的全局作用域中,this和sele引用的都是worker对象。为便于处理数据,Web Worker本身也是一个最小化的运行环境

  • 最小化的navgator对象 : online、appName、appVersion、userAgent、platform
  • 只读的location对象 : 所有属性都是只读的
  • self : 指向全局 worker 对象
  • 所有的ECMA对象,Object、Array、Date等
  • XMLHttpRequest构造器
  • setTimeout、setInterval、clearTimeout()和clearInterval()方法

在worker内部,调用close()方法也可以停止工作。Worker停止工作后就不会再有事件发生。 
另外,Worker的全局作用域中提供了importScripts()方法。这个方法接收一个或多个指向JavaScript文件的URL。每个加载过程都是异步进行的,因此素有的脚本加载并执行完成之后,importScripts()才会执行

importScripts('file1.js','file2.js');
  • 1
  • 1

即使file2.js先于file1.js下载完,执行的时候仍然会按照先后顺序实行。而且,这些脚本是在Worker的全局作用域中执行,如果脚本中包含与页面香瓜你的JavaScript代码,那么脚本可能无法正确运行。

history对象

history对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。 
使用Go()方法可以在用户的历史记录中任意跳转,可以向后也可以向前。这个方法接受一个参数,表示向后或向前跳转的页面数的一个整数值。负数表示向后跳转(类似于单击浏览器的‘后退’按钮),正数表示向前跳转(类似于单击浏览器的“前进”按钮)


history.go(-1);//后退一页
history.go(1);//前进一页
history.go(2);//前进两页
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

也可以给go()方法传递一个字符串参数,此时浏览器会跳转到历史记录中包含该字符串的第一个位置–可能后退,也可能前进,具体看那个位置最近。如果历史记录中不包含该字符串,那么这个方法什么也不做

history.go('wrox.com');//跳到最近的wrox.com页面
  • 1
  • 1

另外,还可以使用两个简写方法back()和forward()来代替go()。这两个方法都可以模仿浏览器的‘后退’和‘前进’按钮。

history.back();//后退一页
history.forward();//前进一页
  • 1
  • 2
  • 1
  • 2

history对象还有一个length属性,保存着历史记录的数量。这个数量包括所有的历史记录,即所有向后和向前的记录。

history在h5中新增的属性和方法

h5中的history对象新增了两个新方法:history.pushState()和history.replaeState(); 
两种方法都允许我们添加和更新历史记录,它们的工作原理相同并且可以添加数量相同的参数。但是pushState()是在history栈中添加一个新的条目,replaceState()是替换当前的记录值。除了方法之外,还有popstate 事件 
pushState(data,title[,url])和replaceState(data,title[,url])参数一样,参数说明如下:

  • data:一个表示状态的对象,json格式数据
  • title:一个string格式的标题(大多数浏览器不支持或忽略这个参数,最好用null代替)
  • url:一个url(用于替换当前URL)

当浏览会话记录的时候,不管点击前进或者后退按钮,还是使用history.go和history.back方法,popstate事件都会被触发。当事件发生时,浏览器会从history中取出URL和对应的state对象替换当前的URL和history.state。通过event.state也可以获取history.state 
需要说明的是pushState只是将当前页面保存到history的历史记录中(并作为最近的一个记录),并且将当前浏览器的地址栏改为参数url指定的值,但并不会加载它。这点与普通的通过链接打开或浏览器地址输入url完全不一样。所以如果想在url改变的时候需要监听popstate事件。

利用history可以弥补ajax无法回退的缺陷。如下方法是模拟ajax操作的实现方法。

<input type="button" value="加1" onclick="add()" /><div id="info" style="border:red 1px solid;width:200px;padding:10px;">0</div>
<script>var info = document.getElementById('info');var i = 1;function add() {var data = {param : i,func : func};info.innerHTML = i;document.title = i;History.push(data);i++;}function func(i) {info.innerHTML = i;document.title = i;}History = function() {  var list = [],index = 1,func, scope;function push(data) {if(typeof data !== 'object') return;if(typeof data.param == undefined || typeof data.func !== 'function') return;func = data.func;scope = data.scope;history.pushState({param: data.param}, index, '#' + index);index++;}window.onpopstate = function(e) {if(e.state) {var state = e.state,param = state.param;if(param) {func.call(scope, param);}}else{if(func){func.call(scope, 0);}}}return {push : push};}();
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

2D绘图(canvas和svg)

SVG

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

canvas

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

Canvas 与 SVG 的比较

下表列出了 canvas 与 SVG 之间的一些不同之处。 
Canvas

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

SVG

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

h5的兼容性问题

IE6/IE7/IE8支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签。但是浏览器支持新标签后,还需要添加标签默认的样式。

H5的新特新及API相关推荐

  1. H5新增了哪些新特性

    目录 前言 1.语义化标签 2.form表单增强 3.视频和音频 4.Canvas绘图 5.SVG绘图 6.地理位置定位(Geolocation API ) 7.拖放API 8.Web Worker ...

  2. H5、C3的新特性有哪些?

    H5.C3的新特性有哪些? HTML5的新增元素: 1.canvas 画布 2.用于媒介回放的video和audio元素 3.本地离线存储.localStorage长期存储数据,浏览器关闭后数据不丢失 ...

  3. java8新特性_Java8新特性之Date API|乐字节

    大家好,我是乐字节的小乐,上篇文章讲述了<Java8新特性之Optional>,接下来,小乐将接着讲述Java8新特性之Date API 2019日历 Java8之Date API Jav ...

  4. 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

    返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API 原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 ...

  5. JAVA 8 新日期和时间API 学习总结

    昨天学了Java8新的时间日期api,以前我们做时间计算大多涉及Date,Calendar类,现在几乎全部有了替代的API,使用更加简单易用,通过几个例子记录一下. 1.取得瞬间点 System.cu ...

  6. php新浪api,php调用新浪短链接API的方法,php调用新浪api_PHP教程

    php调用新浪短链接API的方法,php调用新浪api 本文实例讲述了php调用新浪短链接API的方法.分享给大家供大家参考.具体方法如下: 复制代码 代码如下: //Sina App_Key def ...

  7. 新浪短链api java_php调用新浪短链接API的方法

    本文实例讲述了php调用新浪短链接API的方法.分享给大家供大家参考.具体方法如下: //Sina App_Key define('SINA_APPKEY', '31641035'); functio ...

  8. delphi 调用php接口_新浪图床 API 接口调用与请求方法详细教程

    新浪微博图床API在网上已经很多且大都封装成了API供别人调用,这里分享其核心代码.支持前台跨域请求,以POST方式提交图片即可.新浪图床可以将你的图片远程上传到新浪服务器,你可以选择调用本站的接口, ...

  9. 微软发布新Azure 媒体服务 API(V3),现已全面可用

    利用Azure媒体服务(Azure Media Services),客户可以大规模地编码.保护.编制索引和传送视频.最近,微软发布了在Azure中对此服务的几个增强改进,包括新Azure媒体服务API ...

  10. JDK11的新特性:新的HTTP API

    文章目录 简介 使用HTTP Client请求的基本流程 创建HTTP Client 创建HTTP Request 发送HTTP请求 异步HTTP请求 总结 JDK11的新特性:新的HTTP API ...

最新文章

  1. HTML-加速、再加速
  2. 1_HelloWorld
  3. 多股Litz线制作无线耦合线圈测试
  4. 基于工程经验的『RESTful接口设计规范』
  5. 【PAT甲级 Date时间比较】1006 Sign In and Sign Out (20 分) Java版 5/5通过
  6. Android strings.xml中定义字符串显示空格
  7. accept标头 php,如何在PHP中读取任何请求标头
  8. 桌面环境选择_Fedora 30 正式版发布:引入 Deepin 桌面环境(DDE)
  9. 路面压电发电,应该有前途
  10. 读取、修改、保存图像
  11. 百度地图 城市中心点坐标
  12. PLSQL调整SQL字体大小
  13. 游戏中的物品管理系统
  14. Java 笔试练习 01: T1~19
  15. 商务办公软件应用与实践【8】
  16. 无线射频专题《射频合规,ISM频段》
  17. swiper的使用教程
  18. 2D 横向对抗射击游戏之美
  19. 已到年中,华为坚持今年实现2亿出货量目标,然压力山大
  20. 【Vivado那些事儿】在不重新安装 Vivado 的情况下,是否能够安装 Xilinx USB/Digilent 线缆驱动器?...

热门文章

  1. {分享}《Matrix67:信息学竞赛中可能有用的概率学知识》——Monty Hall问题
  2. u盘文件看得见却打不开_U盘能被识别但打不开怎么解决
  3. pytorch load state dict_Pytorch学习记录-使用Pytorch进行深度学习,保存和加载模型
  4. 运营商屡出奇招,移动物联网卡实名制或能整顿行业乱象
  5. 应用无界——第二届世界区块链大会·乌镇
  6. Java项目:SSM农产品朔源管理系统
  7. centos7盘符 linux_centos7 盘符变动 绑定槽位
  8. 基于android平台的手机安全卫士的设计与实现 开题报告,开题报告-基于android的手机安全卫士的设计与开发.doc...
  9. 安卓12鸿蒙,安卓12,鸿蒙OS2相继发布,微软Windows也坐不住了!
  10. 【运维面试】你能阐述下CI/CD吗?