一、requestAnimationFrame()
1. 早期动画循环
JavaScript 中创建动画的典型方式,就是使用 setInterval() 方法来控制所有动画。
关键是要知道延迟时间多长合适,最平滑动画的最佳循环间隔是 1000ms/60,约等于 17ms。以这个循环间隔重绘的动画是最平滑的,因为这个速度最接近浏览器的最高限速。
问题:间隔时间指定了把动画代码添加到浏览器 UI 线程队列中以等待执行的时间,到时候不一定会执行动画代码。
2. 循环间隔的问题
setInterval() 和 setTimeout() 没有办法确保浏览器按时绘制下一帧。
浏览器使用的计时器并非精确到毫秒级别,进一步恶化了问题。
3. mozRequestAnimationFrame
mozRequestAnimationFrame(),告诉浏览器某些 JavaScript 代码将要执行动画。
一个参数:在重绘屏幕前调用的一个函数。这个函数负责改变下一次重绘时的 DOM 样式。
函数也会接收一个参数:一个时间码(从1970年1月1日起至今的毫秒数),表示下一次重绘的实际发生时间。
要知道距离上一次重绘已经过去了多长时间,可以查询 mozAnimationStartTime,其中包含上一次重绘的时间码。
4. webkitRequestAnimationFrame 与 msRequestAnimationFrame
基于 mozRequestAnimationFrame(),Chrome 和 IE10+也都给出了自己的实现,分别叫 webkitRequestAnimationFrame() 和 msRequestAnimationFrame()。
这两个版本与 Mozilla 的版本有两个方面的微小差异。
首先,不会给回调函数传递时间码,因此你无法知道下一次重绘将发生在什么时间。
其次,Chrome 又增加了第二个可选的参数,即将要发生变化的 DOM 元素。知道了重绘将发生在页面中哪个特定元素的区域内,就可以将重绘限定在该区域中。
Chrome和 IE 没有提供 mozAnimationStartTime 的实现。
Chrome 提供了另一个方法 webkitCancelAnimationFrame(),用于取消之前计划执行的重绘操作。
二、Page Visibility API
Page Visibility API(页面可见性 API):让开发人员知道页面是否对用户可见。
三部分组成:
document.hidden:表示页面是否隐藏的布尔值。页面隐藏包括页面在后台标签页中或者浏览器最小化。
document.visibilityState:表示下列4个可能状态的值。
页面在后台标签页中或浏览器最小化。
页面在前台标签页中。
实际的页面已经隐藏,但用户可以看到页面的预览。
页面在屏幕外执行预渲染处理。
visibilitychange 事件:当文档从可见变为不可见或从不可见变为可见时,触发该事件。
IE 的版本是在每个属性或事件前面加上 ms 前缀,Chrome 是加上 webkit 前缀。
// 检查浏览器是否支持
function isHiddenSupported(){
return typeof (document.hidden || document.msHidden || document.webkitHidden) != "undefined";
}
// 检测页面是否隐藏
if (document.hidden || document.msHidden || document.webKitHidden){
//页面隐藏了
} else {
//页面未隐藏
}
差异最大的是 document.visibilityState 属性。
IE10 中是一个表示 4 种状态的数字值: document.MS_PAGE_HIDDEN (0)、 document.MS_PAGE_VISIBLE (1)、 document.MS_PAGE_PREVIEW (2)、 document.MS_PAGE_PRERENDER (3)。
Chrome 中是 3 个字符串值:“hidden”、“visible”、“prerender”。
三、Geolocation API
地理定位(geolocation)是得到了广泛支持的一个新 API。
JavaScript 代码能够访问到用户的当前位置信息。访问之前必须得到用户的明确许可,即同意在页面中共享其位置信息。
Geolocation API 在浏览器中的实现是 navigator.geolocation 对象。
3 个方法:
(1)getCurrentPosition():获取用户位置
3 个参数:成功回调函数、可选的失败回调函数和可选的选项对象。
成功回调函数,接收到一个 Position 对象参数,该对象有两个属性: coords 和 timestamp。
coords 对象中包含下列与位置相关的信息:
latitude:以十进制度数表示的纬度。
longitude:以十进制度数表示的经度。
accuracy:经、纬度坐标的精度,以米为单位。
失败回调函数,在被调用的时候也会接收到一个参数。这个参数是一个对象,包含两个属性:message 和 code。
message 属性中保存着给人看的文本消息,解释为什么会出错,code 属性中保存着一个数值,表示错误的类型:用户拒绝共享(1)、位置无效(2)或者超时(3)。
选项对象,用于设定信息的类型。
可以设置的选项有三个:enableHighAccuracy 是一个布尔值,表示必须尽可能使用最准确的位置信息,建议保持默认值 false;timeout 是以毫秒数表示的等待位置信息的最长时间;maximumAge 表示上一次取得的坐标信息的有效时间,以毫秒表示,如果时间到则重新取得新坐标信息。
navigator.geolocation.getCurrentPosition(function(position){
drawMapCenteredAt(position.coords.latitude, positions.coords.longitude);
}, function(error){
console.log("Error code: " + error.code);
console.log("Error message: " + error.message);
}, {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 25000
});
(2)watchPosition():跟踪用户位置
接收的参数与 getCurrentPosition() 方法完全相同,相当于定时调用 getCurrentPosition()。
返回一个数值标识符,用于跟踪监控的操作。
(3)clearWatch(watchId):取消监控操作
参数:数值标识符,类似 setTimeout() 和 clearTimeout()。
支持地理定位的浏览器:IE9+、Firefox 3.5+、Opera 10.6+、Safari 5+、Chrome、iOS 版 Safari、Android 版 WebKit。
四、File API
File API(文件 API)的宗旨:为 Web 开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操作。
支持 File API 的浏览器:IE10+、Firefox 4+、Safari 5.0.5+、Opera 11.1+ 和 Chrome。
File API 在表单中的文件输入字段的基础上,又添加了一些直接访问文件信息的接口。HTML5 在 DOM 中为文件输入元素添加了一个 files 集合。在通过文件输入字段选择了一或多个文件时,files 集合中将包含一组 File 对象,每个 File 对象对应着一个文件。
每个 File 对象都有下列只读属性:
name:本地文件系统中的文件名。
size:文件的字节大小。
type:字符串,文件的 MIME 类型。
lastModifiedDate:字符串,文件上一次被修改的时间(Chrome)。
1. FileReader 类型
FileReader 类型实现的是一种异步文件读取机制。(类似 XMLHttpRequest,区别是读取的是文件系统,而不是远程服务器)
FileReader 方法:
readAsText(file,encoding):以纯文本形式读取文件,将读取到的文本保存在 result 属性中。第二个参数用于指定编码类型,可选。
readAsDataURL(file):读取文件并将文件以数据 URI 的形式保存在 result 属性中。
readAsBinaryString(file):读取文件并将一个字符串保存在 result 属性中,字符串中的每个字符表示一字节。
readAsArrayBuffer(file):读取文件并将一个包含文件内容的 ArrayBuffer 保存在 result 属性中。
FileReader 事件:
progress:可判断是否又读取了新数据。
每过 50ms 左右就会触发一次 progress 事件。通过事件对象可以获得与 XHR 的 progress 事件相同的信息(属性):lengthComputable、loaded 和 total。
error:可判断是否发生了错误。
触发 error 事件时,相关的信息将保存到 FileReader 的 error 属性中。这个属性中将保存一个对象,该对象只有一个属性:code 错误码。1-未找到文件,2-安全性错误,3-读取中断,4-文件不可读,5-编码错误。
load:可判断是否已经读完了整个文件。
文件成功加载后会触发 load 事件;如果发生了 error 事件,就不会发生 load 事件。可以通过 FileReader 的 result 属性读取到文件内容。
abort:调用 abort() 方法中断读取过程,会触发 abort 事件。
loadend:已经读取完整个文件,或者读取时发生了错误,或者读取过程被中断。(load、error、abort 事件)
2. 读取部分内容
File 对象支持一个 slice()
方法,接收两个参数:起始字节和要读取的字节数。返回一个 Blob 的实例, Blob 是 File 类型的父类型。
Firefox mozSlice()
Chrome webkitSlice()
通用写法:
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.mozSlice){
return blob.mozSlice(startByte, length);
} else {
return null;
}
}
// 只读取文件的 32B 内容
var blob = blobSlice(files[0], 0, 32);
3. 对象URL
对象 URL (也称 blob URL),指的是引用保存在 File 或 Blob 中数据的 URL。
使用对象 URL 的好处:可以不必把文件内容读取到 JavaScript 中而直接使用文件内容。
创建对象 URL:window.URL.createObjectURL()
传入 File 或 Blob 对象
Chrome window.webkitURL.createObjectURL()
返回值是一个字符串,指向一块内存的地址。可以直接在 DOM 中使用。
使用举例:直接把对象 URL 放在 <img> 标签中,省去把数据先读到 JavaScript 中的麻烦。<img> 标签会找到相应的内存地址,直接读取数据并将图像显示在页面中。
手工释放内存:window.URL.revokeOjbectURL(对象URL)
Chrome window.webkitURL.revokeObjectURL()
支持对象 URL 的浏览器:IE10+、Firefox 4 和 Chrome。
4. 读取拖放的文件
在页面上创建了自定义的放置目标之后,可以从桌面上把文件拖放到该目标。
从桌面上把文件拖放到浏览器,也会触发 drop 事件,可以在 event.dataTransfer. files
中读取到被放置的文件(一个与通过文件输入字段取得的一样的 File 对象)。
5. 使用XHR上传文件
步骤:(表单提交的方式)
首先,创建一个 FormData 对象,通过它调用 append() 方法并传入相应的 File 对象作为参数。
然后,再把 FormData 对象传递给 XHR 的 send() 方法。
支持该方式浏览器: Firefox 4+、Safari 5+和 Chrome。
五、Web 计时
Web 计时机制的核心是 window.performance 对象。
对页面的所有度量信息,包括那些规范中已经定义的和将来才能确定的,都包含在这个对象里面。
performance.navigation 属性:一个对象,包含着与页面导航有关的多个属性。
redirectCount:页面加载前的重定向次数。
type:数值常量,表示刚刚发生的导航类型。
performance.timing 属性:一个对象,这个对象的属性都是时间戳,不同的事件会产生不同的时间值。
支持 Web Timing API 的浏览器:IE10+和 Chrome。
六、Web Workers
Web Workers 让 JavaScript 在后台运行解决问题:长时间运行的 JavaScript 进程导致浏览器冻结用户界面。
支持 Web Workers 的浏览器:IE10+、Firefox 3.5+、Safari 4+、Opera 10.6+、Chrome 和 iOS 版的 Safari。
1. 使用Worker
创建 Web Worker:
var worker = new Worker("js文件名");
浏览器下载 js 文件,但只有 Worker 接收到消息才会实际执行文件中的代码。
给 Worker 传递消息:
worker.postMessage(消息内容);
消息内容可以是任何能够被序列化的值,包括对象参数。
停止 Worker:
worker.terminate();
Worker 通过 message 和 error 事件与页面通信的。
message 事件:与 XDM中的 message 事件行为相同,来自 Worker 的数据保存在 event.data 中。
error 事件:在 Worker 不能完成给定的任务时会触发。事件对象中包含三个属性:filename、lineno 和 message,分别表示发生错误的文件名、代码行号和完整的错误消息。
worker.onmessage = function(event){
var data = event.data;
//对数据进行处理
}
worker.onerror = function(event){
console.log("ERROR: " + event.filename + " (" + event.lineno + "): " + event.message);
};
2. Worker全局作用域
Web Worker 所执行的 JavaScript 代码完全在另一个作用域中,与当前网页中的代码不共享作用域。
在 Web Worker 中,同样有一个全局对象和其他对象以及方法。但是,Web Worker 中的代码不能访问 DOM,也无法通过任何方式影响页面的外观。
Web Worker 中的全局对象是 worker 对象本身。在这个特殊的全局作用域中,this 和 self 引用的都是 worker 对象。
Web Worker 本身是一个最小化的运行环境:
– 最小化的 navigator 对象,包括 onLine、appName、appVersion、userAgent 和 platform 属性;
– 只读的 location 对象;
– setTimeout()、setInterval()、clearTimeout() 和 clearInterval() 方法;
– XMLHttpRequest 构造函数。
Worker 内部,调用 close() 方法也可以停止工作,就像在页面中调用 terminate() 方法。
self.close(); // Web Worker 内部的代码
3. 包含其他脚本
向 Worker 中添加其他脚本:importScripts()
接收一个或多个指向 JavaScript 文件的 URL。
每个加载过程都是异步进行的,因此所有脚本加载并执行之后,importScripts() 才会执行。
总结
- requestAnimationFrame():是一个着眼于优化 JavaScript 动画的 API,能够在动画运行期间发出信号。通过这种机制,浏览器就能够自动优化屏幕重绘操作。
- Page Visibility API:让开发人员知道用户什么时候正在看着页面,而什么时候页面是隐藏的。
- Geolocation API:在得到许可的情况下,可以确定用户所在的位置。在移动 Web 应用中,这个API 非常重要而且常用。
- File API:可以读取文件内容,用于显示、处理和上传。与 HTML5 的拖放功能结合,很容易就能创造出拖放上传功能。
- Web Timing:给出了页面加载和渲染过程的很多信息,对性能优化非常有价值。
- Web Workers:可以运行异步 JavaScript 代码,避免阻塞用户界面。在执行复杂计算和数据处理的时候,这个 API 非常有用;要不然,这些任务轻则会占用很长时间,重则会导致用户无法与页面交互。
上一篇:51-JavaScript高级程序设计-最佳实践2性能&部署
下一篇:53-附录-ECMAScript Harmony