requestAnimationFrame()javascript
每次瀏覽器重繪以前會調用這個方法!!!
php
它接收一個參數,就是回調函數;html
它能夠保證在最佳的間隔時間調用傳入的回調函數,以達到讓屏幕產生最流暢的動畫效果。每次調用這個api它只會調用一次回調函數,而且給回調函數傳入間隔的時間(毫秒)。很適合用js作動畫。java
下面這個方法能夠打印出不一樣瀏覽器兩次重繪的間隔時間(毫秒):git
(function(){
function draw(timestamp){
// 計算兩次重繪的時間間隔
var drawStart=(timestamp||Date.now()),
diff=drawStart-startTime;
//使用diff肯定下一步的重繪時間
// console.log(diff);//這就是當前瀏覽器當前重繪的時間間隔(毫秒)
// 把startTime重寫爲這一次的繪製時間
startTime=drawStart;
// 重繪UI
requestAnimationFrame(draw);
}
var requestAnimationFrame=window.requestAnimationFrame||
window.mozRequestAnimationFrame||
window.webkitRequestAnimationFrame||
window.msRequestAnimationFrame,
startTime=window.mozAnimationStartTime||Date.now();
console.log(startTime);
requestAnimationFrame(draw);
})();
以上代碼只兼容IE、chrome、firefox瀏覽器web
Page Vilibility APIchrome
用於確認頁面是否被隱藏。api
document.hidden: 表示頁面是否隱藏的布爾值。頁面隱藏包含頁面在後臺標籤中或者瀏覽器最小化。數組
document.visibilityState:它有如下幾種可能的值瀏覽器
visible : 頁面內容至少是部分可見。 在實際中,這意味着頁面是非最小化窗口的前景選項卡。
hidden : 頁面內容對用戶不可見。 在實際中,這意味着文檔能夠是一個後臺標籤,或是最小化窗口的一部分,或是在操做系統鎖屏激活的狀態下。
prerender : 頁面內容正在被預渲染且對用戶是不可見的(被document.hidden當作隱藏). 文檔可能初始狀態爲prerender,但毫不會從其它值轉爲該值。 註釋:瀏覽器支持是可選的。
unloaded : 頁面正在從內存中卸載。 註釋:瀏覽器支持是可選的。
visibilitychange:這是一個document能夠監聽的事件,當文檔從可見變爲不可見或者從不可見變爲可見時,觸發該事件。
成功回調函數會接收到一個Position對象參數,給對象有兩個屬性:coords和timestamp:
coords對象中將包含下列與位置相關的信息:
latitude:以十進制表示的緯度。
longitude:以十進制表示的經度。
accuracy:經、緯度座標的經度,以米爲單位。
有些瀏覽器還可能會在coords對象中提供以下屬性:
altitude:以米爲單位的海拔高度,若是沒有相關數據則值爲null。
altitudeAccuracy:海拔高度的精度,以米爲單位,數值越大越不精確。
heading:指南針的方向,0表示正北,值爲NAN表示沒有檢測到數據。
speed:速度,即每秒移動多少米,若是沒有相關數據則值爲null。
在失敗回調函數在被調用的時候也會接收到一個參數,這個參數是一個數組,數組中包含了對象,對象包含兩個屬性:message和code。其中,message屬性中保存着給人看的文本信息,解釋爲何會出錯。而code保存着一個數值。
第三個參數時一個選項對象:能夠設置的選項有三個:
enableHighAccuracy:是一個布爾值,表示必須儘量使用最精準的位置信息。
timeout:以毫秒數表示的等待位置信息的最長時間。
maximumAge:表示上一次取得的座標信息的有效時間,以毫秒錶示,若是時間到則從新取得新座標信息。
function geolocationSupport(){
if(!navigator.geolocation){
alert("你的瀏覽器不支持HTML5 Geolocation");
}else{
getCurrentPosition();
}
}
function getCurrentPosition(){
var options={
enableHighAccuracy:true,
timeout:60000,
maximumAge:60000
}
navigator.geolocation.getCurrentPosition(success,error,options)
}
function success(position)
{
var x=position.coords.longitude;
var y=position.coords.latitude;
alert("經度爲:"+x+"緯度爲:"+y);
}
function error(err)
{
var errorTypes={
1:"用戶拒絕定位服務",
2:"獲取不到定位信息",
3:"獲取定位信息超時"
}
alert(errorTypes[err.code]);
}
window.onload=geolocationSupport();
File API:
當文件輸入字段選擇了一或多個文件時,文件輸入元素的files集合中將包含一組File對象,每一個File對象對應着一個文件。每一個File對象都有下列只讀屬性:
name:本地文件系統中的文件名。
size:文件的字節大小。
type:字符串,文件的MIME類型。
lastModifiedDate:字符串,文件上一次被修改的時間。(chrome)
例如:
<input type="file" id="file_list" multiple="multiple">
按ctrl鍵,能夠選擇多個文件
var fileList=document.getElementById("file_list"); fileList.onchange=function(event){ var files=event.target.files, i=0, len=files.length; console.log(files); while(i<len){ console.log(files[i].name+" ("+files[i].type+", "+files[i].size+" bytes"); i++; } }
FileReader類型
異步
FileReader類型是用來讀取文件的,讀取的文件須要是文件輸入元素的files集合中的File對象。讀取後的數據都將保存在實例的result屬性中,它的實例用如下幾個方法:
readAsText(讀取的文件,可選的指定編碼類型):以純文本形式讀取文件。
readAsDataURL(讀取的文件):讀取文件並將文件以數據URL的形式保存在result屬性中。
readAsBinaryString(讀取的文件) :讀取文件並將以一個字符串保存在result屬性中,字符串中的每一個字符表示一字節。
readAsArrayBuffer(讀取的文件):讀取文件並將一個包含文件內容的ArrayBuffer保存在result屬性中。
因爲讀取過程是異步的,所以FileReader也提供了幾個事件,這幾個事件經過實例監聽:
progress:是否又讀取了新數據,每50ms左右,就會觸發一次。它的事件對象有如下幾個屬性。
lengthComputable:表示進度信息是否可用的布爾值。
loaded:表示已經接收的字節數。
total:表示根據Content-Length響應頭部肯定的預期字節數。
error:因爲種種緣由沒法讀取文件,就會觸發error事件。相關的信息將保存到FileReader的error屬性中。這個屬性中將保存一個對象,該對象只有一個屬性code,即錯誤碼。這個錯誤碼是1表示未找到文件,是2表示安全性錯誤,是3表示讀取中斷,是4表示文件不可讀。
load:文件成功加載後觸發這個事件。
若是項中斷讀取過程,能夠調用abort()方法,這樣就會觸發abort事件。在觸發load、error或abort事件後,會觸發另一個事件loadend。
var fileList=document.getElementById("file_list"); fileList.onchange=function(event){ var info="", output=document.getElementById("file_list"), progress=document.getElementById("progress"), files=event.target.files, type="default", reader=new FileReader(); if(/image/.test(files[0].type)){ reader.readAsDataURL(files[0]);//如果圖片文件,將圖片以數據URI的形式保存在result屬性中 type="image"; }else{ reader.readAsText(files[0]);//若不是圖片文件,將文件以文本的形式保存在result屬性中 type="text"; } reader.onerror=function(){//讀取失敗處理程序 output.innerHTML="Could not read file , error code is"+reader.error.code; } reader.onprogress=function(event){//讀取過程事件處理程序大概50ms執行一次 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; } progress.innerHTML=html; console.log(reader.result); } }
讀取部份內容
File對象還支持一個slice()方法,在firefox中叫mozSlice(),在chrome中叫webkitSlice()。
slice(起始字節,要讀取的字節數):這個是File對象的方法,返回一個Blob的實例,Blob是File類型的父類型。經過FileReader也能夠從Blob中讀取數據。
下面是一個通用的函數:
function blobSlice(blob,startByte,length){//返回一個Blob實例
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;
}
}
Blob類型有一個size屬性和一個type屬性,並且他也支持slice()方法,以便進一步切割數據。經過FileReader也能夠從Blob中讀取數據下面這個例子只讀取文件的32B內容。
var fileList=document.getElementById("file_list");
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;
}
}
fileList.onchange=function(event){
var info="",
output=document.getElementById("file_list"),
progress=document.getElementById("progress"),
files=event.target.files,
reader=new FileReader(),
blob=blobSlice(files[0],0,32);
if(blob){
reader.readAsText(blob);
reader.onerror=function(){
progress.innerHTML="Could not read file,error code is"+reader.error.code;
}
reader.onload=function(){
progress.innerHTML=reader.result;
}
}else{
console.log("Your browser doesn't support slice().");
}
}
對象URL
對象URL也被稱爲blob URL,指的是引用保存在File或Blob中數據的URL。能夠沒必要用FileReader的readAsDataURL()方法來獲取數據的url,而直接可使用文件。
window.URL.createObjectURL(File或Blob對象):返回一個字符串,指向一塊內存的地址。由於這個字符串是URL,因此在DOM中的img元素的src屬性也能使用。
window.URL.revokeObjectURL(url):若是再也不須要相應的數據,最好釋放它佔用的內容。但只要有代碼在引用對象URL,內存就不會釋放。要手工使用這個方法釋放內存。
var fileList=document.getElementById("file_list"); fileList.onchange=function(event){ var info="", output=document.getElementById("file_list"), progress=document.getElementById("progress"), files=event.target.files, reader=new FileReader(), url=window.URL.createObjectURL(files[0]);//返回一個字符串,指向一個內存地址 if(url){ if(/image/.test(files[0].type)){ progress.innerHTML="<img src="+url+">" }else{ progress.innerHTML=" Not an image."; } }else{ progress.innerHTML="your browser doesn't support object URLs."; } }
直接把對象URL放在<img>標籤中,就省去了把數據先讀到javascript中的麻煩。另外一方面,<img>標籤會招到相應的內存地址,直接讀取數據,並將圖像顯示在頁面中。
若是再也不須要相應的數據,最好釋放它佔用的內容。但只要有代碼在引用URL,內存就不會釋放。要手工釋放內存,就要把URL傳給window.URL.revokeObjectURL().
window.URL.revokeObjectURL(url);
雖然,頁面卸載時會自動釋放URL佔用的內存,但最好仍是手動釋放一下,確保儘量少的佔用內存。
支持URL對象的瀏覽器有IE10+、firefox4+、chrome
var droptarget=document.getElementById("droptarget"); function dropEvent(event){ var info="", files,i,len; event.preventDefault();//阻止拖放的默認事件 if(event.type=="drop"){ files=event.dataTransfer.files; i=0; len=files.length; while(i<len){ info+=files[i].name+" ("+files[i].type+", "+files[i].size+" bytes)<br>"; i++; } droptarget.innerHTML=info; } } //給容器添加拖放事件 droptarget.addEventListener("dragenter",dropEvent); droptarget.addEventListener("dragover",dropEvent); droptarget.addEventListener("drop",dropEvent);
使用XHR上傳文件
最好的作法是以表單提交的方式上傳文件,經過使用FormData類型就很容易作到了,建立一個FormData的實例,經過它調用append(鍵,值)方法並傳入相應的File對象做爲參數。而後,再把FormData實例傳遞給XHR的send()方法。
var droptarget=document.getElementById("droptarget"); function dropEvent(event){ var data,xhr, files,i,len; event.preventDefault();//阻止拖放的默認事件 if(event.type=="drop"){ data=new FormData();//建立一個formdata對象 files=event.dataTransfer.files;//讀取到被放置的文件 i=0; len=files.length; while(i<len){ data.append("file"+i,files[i]); console.log(files[i]); i++; } xhr=new XMLHttpRequest(); xhr.open("post","FileAPIExample06Upload.php",true); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ console.log(xhr.responseText); } } xhr.send(data); } } //給容器添加拖放事件 droptarget.addEventListener("dragenter",dropEvent); droptarget.addEventListener("dragover",dropEvent); droptarget.addEventListener("drop",dropEvent);
上面例子建立了一個FormData對象,與每一個文件對應鍵分別是file0、file一、file2這樣的格式。注意,不用額外寫任何代碼,這些文件就能夠做爲表單的值提交。並且,也沒必要使用FileReader,只要傳入File對象便可。
Web 計時
頁面性能一直都是Web開發人員比較關注的領域。但在實際應用中,度量頁面性能的指標,是javascript的Date對象。Web Timing API改變了這個局面,讓開發人員經過javascript就能使用瀏覽器內部的度量結果,給出了頁面加載和渲染過程的不少信息,對性能優化很是有價值。本文將詳細介紹web Timing API——performance對象。
Web計時機制的核心是window.performance對象。對頁面的全部度量信息,包括那些規範中已經定義的和未來才能肯定的,都包含在這個對象裏面。performance對象包括navigation和timing對象。
window.performance.navigation屬性也是一個對象,包含着與頁面導航有關的多個屬性:
redirectCount:頁面加載前的重定向次數;
type:數值常量,表示剛剛發生的導航類型;0:頁面第一次加載;1:頁面重載過;2:頁面是否經過「後退」或「前進」按鈕打開的;
console.log(window.performance.navigation.redirectCount);//頁面重定向次數
console.log(window.performance.navigation.type);//導航類型
window.performance.timing屬性也是一個對象,但這個對象的屬性都是時間戳(從軟件紀元開始通過的毫秒數),這個獨享包括如下屬性:
navigationStart:開始導航到當前頁面的時間;
unloadEventStart:前一個頁面的unload事件的開始時間;(只有在前一個頁面域當前頁面來自同一個域時,這個屬性纔有值,不然,值爲0)
unloadEventEnd:前一個頁面的unload事件結束的時間;(只有在前一個頁面域當前頁面來自同一個域時,這個屬性纔有值,不然,值爲0)
redirectStart:到當前頁面的重定向開始的時間;(只有在前一個頁面域當前頁面來自同一個域時,這個屬性纔有值,不然,值爲0)
redirectEnd:到當前頁面重定向結束的事件;(只有在前一個頁面域當前頁面來自同一個域時,這個屬性纔有值,不然,值爲0)
fetchStart:開始經過HTTP GET取得頁面的時間;
domainLookupStart:開始查詢當前頁面DNS的時間;
domainLookupEnd:查詢當前頁面DNS結束時間;
connectStart:瀏覽器嘗試鏈接服務器的時間;
connectEnd:瀏覽器成功鏈接到服務器的時間;
secureConnectionStart:瀏覽器嘗試以SSL方式鏈接服務器的時間。不能使用SSL方式鏈接時,這個屬性值爲0;
requestStart:瀏覽器開始請求頁面的時間。
responseStart:瀏覽器接收到頁面第一字節的時間。
responseEnd:瀏覽器接收到頁面全部內容的時間。
domLoading:document.readyState變爲「loading」的時間。
domInteractive:document.readyState變爲「interactive」的時間。
domContentLoadedEventStart:發生DOMContentLoaded事件的時間。
domContentLoadedEventEnd:DOMContentLoaded事件已經發生且執行完全部事件處理程序的時間。
domComplete:document.readyState變爲「complete」的時間。
loadEventStart:發生load事件的時間。
loadEventEnd:load事件已經發生且執行完成全部事件處理程序的時間。
console.log(window.performance.timing.navigationStart);//開始導航到當前頁面的時間
console.log(window.performance.timing.unloadEventStart);//前一個頁面的unload事件的開始時間
console.log(window.performance.timing.unloadEventEnd);//前一個頁面的unload事件結束的時間
console.log(window.performance.timing.redirectStart);//到當前頁面的重定向開始的時間
console.log(window.performance.timing.redirectEnd);//到當前頁面重定向結束的事件
console.log(window.performance.timing.fetchStart);//開始經過HTTP GET取得頁面的時間
console.log(window.performance.timing.domainLookupStart);//開始查詢當前頁面DNS的時間
console.log(window.performance.timing.domainLookupEnd);//查詢當前頁面DNS結束時間
console.log(window.performance.timing.connectStart);//瀏覽器嘗試鏈接服務器的時間
console.log(window.performance.timing.connectEnd);//瀏覽器成功鏈接到服務器的時間
console.log(window.performance.timing.secureConnectionStart);//瀏覽器嘗試以SSL方式鏈接服務器的時間。不能使用SSL方式鏈接時,這個屬性值爲0;
console.log(window.performance.timing.requestStart);//瀏覽器開始請求頁面的時間
console.log(window.performance.timing.responseStart);//瀏覽器接收到頁面第一字節的時間
console.log(window.performance.timing.responseEnd);//瀏覽器接收到頁面全部內容的時間
console.log(window.performance.timing.domLoading);//document.readyState變爲「loading」的時間
console.log(window.performance.timing.domInteractive);//document.readyState變爲「interactive」的時間。
console.log(window.performance.timing.domContentLoadedEventStart);//發生DOMContentLoaded事件的時間
console.log(window.performance.timing.domContentLoadedEventEnd);//DOMContentLoaded事件已經發生且執行完全部事件處理程序的時間
console.log(window.performance.timing.domComplete);//document.readyState變爲「complete」的時間
console.log(window.performance.timing.loadEventStart);//發生load事件的時間
console.log(window.performance.timing.loadEventEnd);//load事件已經發生且執行完成全部事件處理程序的時間。
經過這些值,就能夠全面瞭解頁面在被加載到瀏覽器的過程當中都經歷了哪些階段,而哪些階段多是影響性能的瓶頸。
Web Workers(多線程)
可讓單線程的js運行多線程。
使用worker
實例化Worker對象並傳入要執行的javascript文件名就能夠建立一個新的Web Worker。例如:
var worker = new worker("worker.js");
能夠向worker.js內傳入任何可序列化的對象(調用的是worker的postMessage()方法)
worker.postMessage({
type:"command",
message:"start"
});
Worker是經過message和error事件與頁面進行通訊的,來自worker.js的數據保存在event.data中。worker返回的數據也能夠是任何能被序列化的值:
worker.onmessage=function(event){
var data=event.data;
//對數據進行處理
}
Worker不能完成給定的任務時會觸發error事件。具體來講,Worker內部的javascript在執行過程當中只要遇到錯誤,就會觸發error事件。發生error事件時,事件對象中包含3個屬性:
filename、lineno、message,分別表示發生錯誤的文件名、代碼行號和完整的錯誤信息。
worker.onerror=function(event){
console.log("Error: "+event.filename+" ("+event.lineno+"): "+event.message);
}
任什麼時候候,只要調用terminate()方法就能夠中止Worker的工做。並且,Worker中的代碼會當即中止執行,後續的全部過程都不會再發生(包括error和message事件也不會觸發)。
worker.terminate();//當即中止Worker的工做
在worker打開的js內能夠向主頁面傳值,經過postMessage(data)方法,能夠傳入任何值;
下面是一個綜合例子:
var w,
output=document.getElementById("output");
function startWorker(){
if(typeof Worker!== "undefined"){
if(typeof(w)==="undefined"){
w=new Worker("worker.js");
}
//傳給worker.js點數據
w.postMessage({
type:"command",
message:"start"
});
w.onmessage=function(event){
output.innerHTML=event.data;
}
w.onerror=function(event){
console.log("Error: "+event.filename+" ("+event.lineno+"): "+event.message);
}
}else{
output.innerHTML="瀏覽器不支持worker";
}
}
function stopWorker(){
w.terminate();
}
如下是worker.js內的代碼:
// worker.js接收頁面傳來的數據 self.onmessage=function(event){ console.log(event.data); } self.onerror=function(){ console.log("接收頁面傳來的值失敗"); } function timedCount(){ for(let i=0,len=100000000;i<len;i++){ if(i%100000===0){ //this指向worker自己,self也是,但這個worker和頁面中的worker不是同一個worker postMessage(i); // this.postMessage(i); // self.postMessage(i); } } } timedCount();
在woker.js內調用close()方法,能夠中止worker運行
self.close();
this.close();
close();
Worker全局做用域
關於web Worker 最重要的是要知道它所執行的javascsript代碼徹底在另外一個做用域中,與當前網頁的代碼不共享做用域。在web worker中,一樣有一個全局對象和其它對象以及方法。可是,web Worker中的全局對象是worker對象自己。也就是說,在這個特殊的全局做用域中,this和self引用的都是worker對象。爲便於處理數據,web worker自己也是一個最小化的運行環境。
一、最小化的navigator對象,包括onLine、appName、appVersion、userAgent和platform屬性;
二、只讀的location對象;
三、setTimeout()、setInterval()、clearTimeout()、clearInterval();
四、XMLHttpRequest構造函數;
顯然,web worker的運行環境與頁面環境相比,功能是至關有限的。
包含其它腳本
沒法在worker中動態建立script標籤,可是能夠調用importScripts()方法,能夠引入其它js腳本。例如:
importScripts("file1.js","file2.js");
即便files2.js比file1.js先下載完,可是執行的時候仍是會按照順序執行。