国产亚洲福利精品一区二区,久久精品国产亚洲AV无码娇色,日韩亚洲人成在线综合日本 http://www.tkk7.com/xiaomage234/category/50778.html生命本就是一次凄美的漂流,記憶中放不下的,永遠(yuǎn)是孩提時(shí)代的那一份浪漫與純真!zh-cnMon, 03 Sep 2012 19:47:00 GMTMon, 03 Sep 2012 19:47:00 GMT60Chrome瀏覽器上的語(yǔ)音輸入功能http://www.tkk7.com/xiaomage234/archive/2012/09/03/386842.html小馬歌小馬歌Mon, 03 Sep 2012 02:24:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/09/03/386842.htmlhttp://www.tkk7.com/xiaomage234/comments/386842.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/09/03/386842.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/386842.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/386842.html

 使用Chrome瀏覽器的同學(xué)應(yīng)該會(huì)經(jīng)常看到一些網(wǎng)站的搜索框右邊有一個(gè)麥克風(fēng)的標(biāo)志,點(diǎn)擊圖標(biāo)后即可連接麥克風(fēng)進(jìn)行語(yǔ)音識(shí)別搜索,那么這是如何實(shí)現(xiàn)的呢?

淘寶網(wǎng)上的語(yǔ)音搜索功能

其實(shí)非常簡(jiǎn)單,這是html5下一個(gè)新的屬性,通過(guò)調(diào)用google的語(yǔ)音服務(wù)api,用于支持網(wǎng)頁(yè)內(nèi)的語(yǔ)音識(shí)別輸入功能。

只需要在輸入框的input上添加一個(gè)x-webkit-speech 屬性就可以了。

如本博客的搜索框:

<input type="text"  name="edtSearch" x-webkit-speech id="edtSearch" value="Search...." onfocus="if (this.value == 'Search....') {this.value = '';}" onblur="if (this.value == '') {this.value = 'Search....';}" />

另外它還可以添加以下屬性:

語(yǔ)言種類: lang="zh-CN"

發(fā)聲改變時(shí)觸發(fā)相關(guān)語(yǔ)音識(shí)別:onwebkitspeechchange="foo()"

讓語(yǔ)音輸入的內(nèi)容更加精確盡量接近搜索內(nèi)容:x-webkit-grammar="bUIltin:search"

通過(guò)平時(shí)的使用感覺(jué)如果發(fā)音清晰的話,識(shí)別率還算不錯(cuò)。這是google應(yīng)用于Chrome瀏覽器上的一項(xiàng)實(shí)驗(yàn)性功能,以上屬性同樣也對(duì)webkit內(nèi)核瀏覽器生效。

相關(guān)W3C標(biāo)準(zhǔn)參考文檔:http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html



小馬歌 2012-09-03 10:24 發(fā)表評(píng)論
]]>
人人網(wǎng)首頁(yè)拖拽上傳詳解(HTML5 Drag&Drop、FileReader API、FormData) 【轉(zhuǎn)】http://www.tkk7.com/xiaomage234/archive/2012/03/19/372202.html小馬歌小馬歌Mon, 19 Mar 2012 08:35:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/19/372202.htmlhttp://www.tkk7.com/xiaomage234/comments/372202.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/19/372202.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/372202.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/372202.html人人網(wǎng)首頁(yè)拖拽上傳詳解

  早在公元2011年6月3日傍晚,人人網(wǎng)推出了一個(gè)很裝B且完全無(wú)視IE瀏覽器的功能——拖拽上床。哦,Sorry, 是拖拽上傳。本文將重點(diǎn)介紹實(shí)現(xiàn)拖拽上傳的幾個(gè)HTML5技術(shù):Drag&DropFileReader APIFormData

  關(guān)于這個(gè)拖拽上傳,其實(shí)國(guó)外有很多網(wǎng)站已經(jīng)有這樣的應(yīng)用,最早推出拖拽上傳應(yīng)用的是Gmail,它支持標(biāo)準(zhǔn)瀏覽器下拖拽本地文件到瀏覽器中作為郵件的附件發(fā)送。人人網(wǎng)的這個(gè)拖拽上傳也是同理,可以讓使用標(biāo)準(zhǔn)瀏覽器的用戶通過(guò)簡(jiǎn)單的拖拽行為,將本地文件夾中的照片直接上傳到人人網(wǎng),用戶體驗(yàn)?zāi)艿玫教嵘耐瑫r(shí),也希望借此機(jī)會(huì)推廣一下標(biāo)準(zhǔn)瀏覽器,淘汰IE。人人網(wǎng)當(dāng)時(shí)也向廣大用戶推出升級(jí)瀏覽器活動(dòng),并喊出口號(hào):”工欲善其計(jì)算機(jī),必先利其瀏覽器”。本次拖拽上傳的宣傳口號(hào):你敢”脫”,我就敢上傳…

人人網(wǎng) - 拖拽上傳

  言歸正題,首先看看效果,大家如果有人人網(wǎng)帳號(hào)的話可以在首頁(yè)試一試拖拽上傳功能,下面是演示視頻:

拖拽上傳應(yīng)用主要使用了以下HTML5技術(shù):

  • Drag&Drop : HTML5基于拖拽的事件機(jī)制.
  • File API :  可以很方便的讓W(xué)eb應(yīng)用訪問(wèn)文件對(duì)象,F(xiàn)ile API包括FileListBlobFileFileReaderURI scheme,本文主要講解拖拽上傳中用到的FileList和FileReader接口。
  • FormData : FormData是基于XMLHttpRequest Level 2的新接口,可以方便web應(yīng)用模擬Form表單數(shù)據(jù),最重要的是它支持文件的二進(jìn)制流數(shù)據(jù),這樣我們就能夠通過(guò)它來(lái)實(shí)現(xiàn)AJAX向后端發(fā)送文件數(shù)據(jù)了。

HTML5 Drag&Drop 拖拽事件

  關(guān)于Drag&Drop拖拽事件,之前我寫過(guò)一篇專門介紹的文章《給力的 Google HTML5 訓(xùn)練營(yíng)(HTML5 Drag&Drop 拖拽、FileReader實(shí)例教程)》,那篇文章詳細(xì)講解了Drag & Drap事件的原理和代碼實(shí)例,這里的拖拽上傳實(shí)現(xiàn)原理基本上是一樣的,大家有興趣或不太了解的話可以先看看那篇文章,我在這里就不再過(guò)多啰嗦了~下面直接出拖拽上傳簡(jiǎn)要代碼實(shí)例:

var oDragWrap = document.body;

 

//拖進(jìn)
oDragWrap.addEventListener(’dragenter’, function(e) {
 e.preventDefault();
}, false);

//拖離
oDragWrap.addEventListener(’dragleave’, function(e) {
 dragleaveHandler(e);
}, false);

//拖來(lái)拖去 , 一定要注意dragover事件一定要清除默認(rèn)事件
//不然會(huì)無(wú)法觸發(fā)后面的drop事件
oDragWrap.addEventListener(’dragover’, function(e) {
 e.preventDefault();
}, false);

//扔
oDragWrap.addEventListener(’drop’, function(e) {
 dropHandler(e);
}, false);

var dropHandler = function(e) {
//將本地圖片拖拽到頁(yè)面中后要進(jìn)行的處理都在這
}

獲取文件數(shù)據(jù) HTML5 File API

  在之前那篇文章中我也有介紹過(guò)關(guān)于File API中的FileReader接口,作為 File API 的一部分,FileReader 專門用于讀取文件,根據(jù) W3C 的定義,F(xiàn)ileReader 接口 “提供一些讀取文件的方法與一個(gè)包含讀取結(jié)果的事件模型”。關(guān)于FileReader的詳細(xì)介紹和代碼實(shí)例大家可以先去看看那篇文章

  今天我著重介紹一下File API中的FileList接口,它主要通過(guò)兩個(gè)途徑獲取本地文件列表,一是<input type=”file”>的表單形式,另一種則是e.dataTransfer.files拖拽事件傳遞的文件信息。很顯然,我們這里會(huì)用到后者。

var fileList = e.dataTransfer.files;

  使用files方法將會(huì)獲取到拖拽文件的數(shù)組形勢(shì)的數(shù)據(jù),每個(gè)文件占用一個(gè)數(shù)組的索引,如果該索引不存在文件數(shù)據(jù),將返回null值。可以通過(guò)length屬性獲取文件數(shù)量.

var fileNum = fileList.length;

  拖拽上傳需要注意的是需要判斷兩個(gè)條件,1:拖拽的是文件不是頁(yè)面中的元素; 2:拖拽的是圖片而不是其它文件,可以通過(guò)file.type屬性獲取文件的類型

//檢測(cè)是否是拖拽文件到頁(yè)面的操作
if (fileList.length === 0) {return;};
//檢測(cè)文件是不是圖片
if (fileList[0].type.indexOf(’image’) === -1) {return;}

  下面讓我們來(lái)看看如何結(jié)合之前的拖拽事件來(lái)實(shí)現(xiàn)拖拽圖片并在頁(yè)面中進(jìn)行預(yù)覽:

var dropHandler = function(e) {
 e.preventDefault();

 

 //獲取文件列表
 var fileList = e.dataTransfer.files;

 //檢測(cè)是否是拖拽文件到頁(yè)面的操作
 if (fileList.length == 0) {return;};

 //檢測(cè)文件是不是圖片
 if (fileList[0].type.indexOf(’image’) === -1) {return;}

 //實(shí)例化file reader對(duì)象
 var reader = new FileReader();
 var img = document.createElement(’img’);

 reader.onload = function(e) {
  img.src = this.result;
  oDragWrap.appendChild(img);
 }
 reader.readAsDataURL(fileList[0]);

}

  這里有一個(gè)簡(jiǎn)單的拖拽圖片預(yù)覽的Demo

  這時(shí)你如果用FireBug等類似調(diào)試工具查看DOM的話,會(huì)看到<img>標(biāo)簽的src屬性是一個(gè)超長(zhǎng)的文件二進(jìn)制數(shù)據(jù),所以如果DOM有很多這類圖片,那就要當(dāng)心瀏覽器性能了,因?yàn)檫@些數(shù)據(jù)極大地?cái)U(kuò)充的頁(yè)面的代碼量,而每次頁(yè)面的reflow都會(huì)對(duì)瀏覽器形成很大的負(fù)擔(dān),So,如果這些圖片還在DOM中,那就盡量不要做動(dòng)畫或任何重繪操作,如果真的要做就盡量讓圖片脫離文檔流,讓其絕對(duì)定位比較靠譜。

補(bǔ)充:可以使用window.URL.createObjectURL(file)來(lái)獲取文件的URL(Chrome下用window.webkitURL.createObjectURL(file)),這種方式獲取的URL要比上面說(shuō)的readAsDataURL簡(jiǎn)短很多。而且可以省去使用FileReader。這里感謝BinBinLiao的留言建議:) 下面是使用readAsDataURL與createObjectURL生成的代碼對(duì)比:

readasdataurl-vs-createobjecturl

優(yōu)化后的代碼:(紅色為優(yōu)化的代碼)

var dropHandler = function(e) {
 e.preventDefault();

 

 var fileList = e.dataTransfer.files;  //獲取文件列表
 var img = document.createElement(’img’);

 //檢測(cè)是否是拖拽文件到頁(yè)面的操作
 if (fileList.length == 0) {return;};

 //檢測(cè)文件是不是圖片
 if (fileList[0].type.indexOf(’image’) === -1) {return;}
 

 if (window.URL.createObjectURL) {
  //FF4+
  img.src = window.URL.createObjectURL(fileList[0]);
 } else if (window.webkitURL.createObjectURL) {
  //Chrome8+
  img.src = window.webkitURL.createObjectURL(fileList[0]);
 } else {
  //實(shí)例化file reader對(duì)象
  var reader = new FileReader();

 

  reader.onload = function(e) {
   img.src = this.result;
   oDragWrap.appendChild(img);
  }
  reader.readAsDataURL(fileList[0]);
 }

}

  需要注意的是,window.URL.createObjectURL是有生命周期的,也就意味著你每用此方法獲取URL,其生命周期都會(huì)和DOM一樣,它會(huì)單獨(dú)占用內(nèi)存,所以當(dāng)刪除圖片或不再需要它是,記得用window.URL.revokeObjectURL(file)來(lái)釋放其內(nèi)存。當(dāng)然,如果你沒(méi)有釋放,刷新頁(yè)面也是可以釋放的。

AJAX上傳圖片(file.getAsBinary & FormData)

  既然已經(jīng)獲取到了拖拽到web頁(yè)面中圖片的數(shù)據(jù),下一步就是將其發(fā)送到服務(wù)器端了。

  話說(shuō)HTML5時(shí)代之前,AJAX傳輸文件二進(jìn)制流數(shù)據(jù)是不可能完成的事情,而現(xiàn)在我們完全可以通過(guò)file.getAsBinary獲取文件的二進(jìn)制數(shù)據(jù)流,進(jìn)而將其當(dāng)做XHR的data數(shù)據(jù)傳送到后端,8過(guò)由于Chrome不支持file的getAsBinary方法,F(xiàn)F3.6+支持此方法。所以Chrome就要另尋它法了,這時(shí)我們發(fā)現(xiàn)XMLHttpRequest Level 2中的FormData接口完美解決了這個(gè)問(wèn)題,它可以很快捷的模擬Form表單數(shù)據(jù)并通過(guò)AJAX發(fā)送至后端,F(xiàn)ormData的支持情況是FF5及以上支持,Chrome12及以上支持。

   file.getAsBinary獲取文件流很簡(jiǎn)單,但是要想上傳數(shù)據(jù),就要模擬一下表單的數(shù)據(jù)格式了,首先看看模擬表單的js代碼, FormData模擬表單數(shù)據(jù)時(shí)更是簡(jiǎn)潔,不用麻煩的去拼字符串,而是直接將數(shù)據(jù)append到formdata對(duì)象中即可:

var xhr = new XMLHttpRequest();
var url = ‘http://upload.renren.com/……’;
var boundary = ‘———————–’ + new Date().getTime();
var fileName = file.name;

 

xhr.open(”post”, url, true);
xhr.setRequestHeader(’Content-Type’, ‘multipart/form-data; boundary=’ + boundary);

if (window.FormData) {
 //Chrome12+
 var formData = new FormData();
 formData.append(’file’, file);
 formData.append(’hostid’, userId);
 formData.append(’requestToken’, t);

 data = formData;
} else if (file.getAsBinary) {
 //FireFox 3.6+
 data = “–” +
 boundary +
 crlf +
 ”Content-Disposition: form-data; ” +
 ”name=\”" +
 ’file’ +
 ”\”; ” +
 ”filename=\”" +
 unescape(encodeURIComponent(file.name)) +
 ”\”" +
 crlf +
 ”Content-Type: image/jpeg” +
 crlf +
 crlf +
 file.getAsBinary() +
 crlf +
 ”–” +
 boundary +
 crlf +
 ”Content-Disposition: form-data; ” +
 ”name=\”hostid\”" +
 crlf +
 crlf +
 userId +
 crlf +
 ”–” +
 boundary +
 crlf +
 ”Content-Disposition: form-data; ” +
 ”name=\”requestToken\”" +
 crlf +
 crlf +
 t +
 crlf +
 ”–” +
 boundary +
 ’–’;
}

xhr.send(data);

首先表單數(shù)據(jù)headers頭信息需要以下兩項(xiàng):

  • Content-Type : 設(shè)置其為multipart/form-data來(lái)模擬表單數(shù)據(jù)
  • boundary : 表單數(shù)據(jù)中的分隔符,用于分隔不同的文件或表單項(xiàng),這是服務(wù)器端設(shè)置的格式。

發(fā)送時(shí)的post數(shù)據(jù)類似這樣:

————————-1323611763556
Content-Disposition: form-data; name=”file”; filename=”4.jpg”
Content-Type: image/jpeg

 

ÿØÿà?JFIF?…這里是文件二進(jìn)制流…~iúoî­5P%-vãîHü 4QHgÿÙ
————————-1323611763556
Content-Disposition: form-data; name=”hostid”

229421603
—————————–1323612996486

Content-Disposition: form-data; name=”requestToken”

369009193
————————-1323611763556–

好了,現(xiàn)在文件上傳成功后你就可以按照平常AJAX的操作來(lái)進(jìn)行后續(xù)處理了。

最后,再來(lái)總結(jié)一下拖拽上傳的技術(shù)要點(diǎn):

  1. 監(jiān)聽(tīng)拖拽:監(jiān)聽(tīng)頁(yè)面元素的拖拽事件,包括:dragenter、dragover、dragleave和drop,一定要將dragover的默認(rèn)事件取消掉,不然無(wú)法觸發(fā)drop事件。如需拖拽頁(yè)面里的元素,需要給其添加屬性draggable=”true”;
  2. 獲取拖拽文件:在drop事件觸發(fā)后通過(guò)e.dataTransfer.files獲取拖拽文件列表,.length屬性獲取文件數(shù)量,.type屬性獲取文件類型。
  3. 讀取圖片數(shù)據(jù)并添加預(yù)覽圖:實(shí)例化FileReader對(duì)象,通過(guò)其readAsDataURL(file)方法獲取文件二進(jìn)制流,并監(jiān)聽(tīng)其onload事件,將e.result賦值給img的src屬性,最后將圖片append到DOM中。
  4. 發(fā)送圖片數(shù)據(jù):使用file.getAsBinary 和 FormData分別模擬表單數(shù)據(jù)AJAX提交文件流。

OK,拖拽上傳就講到這里,歡迎大家一起探討。



小馬歌 2012-03-19 16:35 發(fā)表評(píng)論
]]>
HTML5 Geolocation APIhttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372045.html小馬歌小馬歌Fri, 16 Mar 2012 07:25:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372045.htmlhttp://www.tkk7.com/xiaomage234/comments/372045.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372045.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/372045.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/372045.html

HTML5提供了一組API用來(lái)獲取用戶的地理位置,如果瀏覽器支持且設(shè)備具有定位功能,就能夠直接使用這組API來(lái)獲取當(dāng)前位置信息。

該API是navigator對(duì)象的一個(gè)屬性 – Geolocation。目前除了ie內(nèi)核瀏覽器外,其他瀏覽器的最新版本基本都支持Geolocation。同時(shí),移動(dòng)設(shè)備IOS 3.0+ 和 Android 2.0+ 系統(tǒng)也支持它,現(xiàn)在很多移動(dòng)設(shè)備的應(yīng)用加入了地理定位的元素。

那么我們接下來(lái)看如何使用Geolocation API:

一、檢查瀏覽器是否支持Geolocation

var hasGeolocation = !!(navigator.geolocation);
if(hasGeolocation){
alert(“瀏覽器支持hasGeolocation”);
}

二、navigator.geolocation 的方法:

* navigator.geolocation有三個(gè)方法,分別是getCurrentPosition()、watchPosition()和clearWatch()

getCurrentPosition()方法

* getCurrentPosition()方法檢索用戶的當(dāng)前位置,但只檢索一次。當(dāng)該方法被腳本調(diào)用時(shí),方法以異步的方式來(lái)嘗試獲取宿主設(shè)備的當(dāng)前位置。

* 該方法最多可以有三個(gè)參數(shù):

geolocationSuccess:帶回當(dāng)前位置的回調(diào)(callback)(必需的)
geolocationError:有錯(cuò)誤發(fā)生時(shí)使用的回調(diào)(可選的)
geolocationOptions:地理位置選項(xiàng)(可選的)

調(diào)用如下所示:


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

watchPosition()方法

* watchPosition()方法定期輪詢用戶的位置,查看用戶的位置是否發(fā)生改變。其最多可帶三個(gè)參數(shù)。

調(diào)用如下所示:


var watchPositionHandler = navigator.geolocation.watchPosition(geolocationSuccess, geolocationError, geolocationOptions);

clearWatch()方法

* clearWatch()方法終止正在進(jìn)行的watchPosition(),該方法只能帶一個(gè)參數(shù)。在調(diào)用時(shí),其找到之前已經(jīng)開(kāi)始了的watchID參數(shù)并立即停止它。

調(diào)用如下所示:


navigator.geolocation.clearWatch(watchID);

三、navigator.geolocation返回一個(gè)Position對(duì)象:

* Position對(duì)象有兩個(gè)屬性:timestamp和coords。timestamp屬性表示地理位置數(shù)據(jù)的創(chuàng)建時(shí)間,coords屬性又包含七個(gè)屬性:

coords.latitude:估計(jì)緯度
coords.longitude:估計(jì)經(jīng)度
coords.altitude:估計(jì)高度
coords.accuracy:所提供的以米為單位的經(jīng)度和緯度估計(jì)的精確度
coords.altitudeAccuracy:所提供的以米為單位的高度估計(jì)的精確度
coords.heading: 宿主設(shè)備當(dāng)前移動(dòng)的角度方向,相對(duì)于正北方向順時(shí)針計(jì)算
coords.speed:以米每秒為單位的設(shè)備的當(dāng)前對(duì)地速度

* 注意altitude, altitudeAccuracy, heading, speed不一定被瀏覽器支持,所以大家最好看一下官方規(guī)范的描述,多一些了解。

四、注意事項(xiàng)

* Geolocation App是不能直接訪問(wèn)設(shè)備的,只能通過(guò)請(qǐng)求瀏覽器來(lái)訪問(wèn)設(shè)備;
* Geolocation涉及到用戶隱私,在獲取 Geolocation 的時(shí)候,需要先征求用戶的意思。
* Geolocation目前沒(méi)有比較好的前端兼容解決方案,但是在移動(dòng)設(shè)備 iOS 和 Android上,我們可以大膽嘗試使用。



小馬歌 2012-03-16 15:25 發(fā)表評(píng)論
]]>
學(xué)習(xí)html5的history APIhttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372044.html小馬歌小馬歌Fri, 16 Mar 2012 07:24:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372044.htmlhttp://www.tkk7.com/xiaomage234/comments/372044.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372044.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/372044.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/372044.html

不得不佩服下谷歌Chrome團(tuán)隊(duì),利用HTML5和CSS3實(shí)現(xiàn)了一本相當(dāng)漂亮的在線電子書:《關(guān)于瀏覽器和互聯(lián)網(wǎng)20件事》。

訪問(wèn)地址:http://www.20thingsilearned.com

話說(shuō)這本電子書已經(jīng)出來(lái)很久了,不過(guò)今天來(lái)看依然覺(jué)得相當(dāng)?shù)馁潯N覀儫o(wú)需刷新頁(yè)面,就可以來(lái)回切換電子書頁(yè)面,這正是OPOA(One Page One Application)的完美體現(xiàn)。

現(xiàn)在正在學(xué)習(xí)關(guān)于history API這方面的東西,所以特別感興趣的是他們?nèi)绾问褂脀indow.history.pushState()和window.history.replaceState()來(lái)做頁(yè)面之間的不刷新切換。

今天查閱了一些資料,基本上對(duì)history API有了一個(gè)基本了解。

首先要說(shuō)的就是history是個(gè)全局,即window.history。看到這個(gè)變量名你一定很熟悉,因?yàn)榻?jīng)常可以看到用window.history.back()或者window.history.go(-1)來(lái)返回上一頁(yè)的JavaScript代碼。

所以history并不是什么新東西,在HTML4的時(shí)代,我們可以使用它的這幾個(gè)屬性和方法:

length:歷史堆棧中的記錄數(shù)。

back():返回上一頁(yè)。

forward():前進(jìn)到下一頁(yè)。

go([delta]):delta是個(gè)數(shù)字,如果不寫或?yàn)?,則刷新本頁(yè);如果為正數(shù),則前進(jìn)到相應(yīng)數(shù)目的頁(yè)面;若為負(fù)數(shù),則后退到相應(yīng)數(shù)目的頁(yè)面。

現(xiàn)在,HTML5為其又添加了以下2個(gè)方法:

pushState(data, title [, url]):往歷史堆棧的頂部添加一條記錄。data為一個(gè)對(duì)象或null,它會(huì)在觸發(fā)window的popstate事件(window.onpopstate)時(shí),作為參數(shù)的state屬性傳遞過(guò)去;title為頁(yè)面的標(biāo)題,但當(dāng)前所有瀏覽器都忽略這個(gè)參數(shù);url為頁(yè)面的URL,不寫則為當(dāng)前頁(yè)。

replaceState(data, title [, url]):更改當(dāng)前頁(yè)面的歷史記錄。參數(shù)同上。這種更改并不會(huì)去訪問(wèn)該URL。不過(guò)目前只有Safari 5.0+、Chrome 8.0+、Firefox 4.0+和iOS 4.2.1+支持。如果想兼容老瀏覽器的話,可以試試History.js,而且它還修正了一些bug。

當(dāng)然,在移動(dòng)平臺(tái)上,我們可以大膽嘗試html5的history API。ios3.0+ 和Android2.0+ 平臺(tái)的內(nèi)置瀏覽器對(duì)history都比較完美了,利用它我們可以web app更趨向與native app。

下面,推薦幾篇文章:

.Manipulating the browser history

.Session history and navigation

.Manipulating History for Fun & Profit



小馬歌 2012-03-16 15:24 發(fā)表評(píng)論
]]>
HTML5 修改瀏覽器url而不刷新頁(yè)面【轉(zhuǎn)】http://www.tkk7.com/xiaomage234/archive/2012/03/16/372043.html小馬歌小馬歌Fri, 16 Mar 2012 07:18:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372043.htmlhttp://www.tkk7.com/xiaomage234/comments/372043.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/16/372043.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/372043.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/372043.html
嘛,起因是黑子大叔在微博上的一條@信息,找起了這個(gè)的實(shí)現(xiàn),看了一圈google的中文信息內(nèi)似乎還沒(méi)有怎么提到這個(gè)的內(nèi)容,就發(fā)表上來(lái)。
詳細(xì)效果就是類似于用Firefox4+/Chrome 5+/Safari 5+/Opera 11.5+登錄新浪微博后看到的個(gè)人時(shí)間軸,在翻頁(yè)時(shí)可以觀察到這個(gè)效果,地址欄URL變動(dòng),但是頁(yè)面沒(méi)有刷新,用firebug觀察也觀察不到刷新整個(gè)頁(yè)面,只有ajax請(qǐng)求的翻頁(yè)數(shù)據(jù)。從先前的理解來(lái)說(shuō),URL的修改必然引起(請(qǐng)注意我不是在說(shuō)通過(guò)錨點(diǎn)修改)瀏覽器重載頁(yè)面,但利用HTML5新加入的history.pushState();和history.replaceState();可以完全自己維護(hù)一個(gè)歷史記錄列表繞開(kāi)歷史記錄完全由瀏覽器控制的機(jī)制,從而實(shí)現(xiàn)比錨點(diǎn)更加完美的一種頁(yè)內(nèi)更新的體驗(yàn)。
代碼方面很簡(jiǎn)單,只要在需要修改url的地方插入一行:
window.history.pushState({"html":response.html,"pageTitle":response.pageTitle}, 'title', urlPath);
//三個(gè)參數(shù),分別為:狀態(tài)對(duì)象,標(biāo)題(目前被瀏覽器忽略),地址
即可在歷史記錄里面產(chǎn)生一個(gè)新的歷史記錄(另一個(gè)replaceState方法參數(shù)完全相同,只是替代掉當(dāng)前的狀態(tài))。
在體驗(yàn)上,非常接近于使用錨點(diǎn)(window.location = “#foo”;),但是mozilla的文檔提出了以下三點(diǎn)好處:
新的URL可以是和原始頁(yè)面URL同域下的任何URL,如果用錨點(diǎn),只能更新#后面的部分
僅在需要時(shí)更新URL,錨點(diǎn)的歷史記錄在相同時(shí)不會(huì)創(chuàng)建(即當(dāng)前已經(jīng)是”#foo”的情況下,如果再將當(dāng)前頁(yè)面錨點(diǎn)設(shè)置為”#foo”,不會(huì)產(chǎn)生新的歷史記錄)
可以記錄下任意類型的數(shù)據(jù),使用錨點(diǎn)的話將要自己維護(hù)一份歷史數(shù)據(jù)列表或者把數(shù)據(jù)轉(zhuǎn)碼到一個(gè)字符串里
(翻譯&描述的有點(diǎn)別扭,見(jiàn)笑了,不過(guò)其實(shí)應(yīng)該自己也能體會(huì)到這些好處才是)
我自己實(shí)現(xiàn)的一個(gè)例子:
http://vifix.cn/atelier/demos/html5-update-browser-url-without-reloading-page
代碼:
<?php
if(!isset($_REQUEST['page'])){
    $page = 1;
}
else{
    $page = intval($_REQUEST['page']);
}
 
if(isset($_REQUEST['ajaxload'])){
    echo "第{$page}頁(yè)的內(nèi)容";
    die;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>HTML5 修改瀏覽器url而不刷新頁(yè)面</title>
<script type="text/javascript">
var domLoaded = function(){
    if(ua != null && ua[1] < 10){
        alert('您的瀏覽器不支持');
        return ;
    }
 
    if(location.href.indexOf("?") > -1){
        var urlparts = location.href.match(/(.+?)\?.+/i);
        var urlbase = urlparts[1];
    }
    else{
        var urlbase = location.href;
    }
    var page = <?php echo $page;?>;
    var ua = window.navigator.userAgent.match(/msie (\d\.\d)/i);
    var content = document.getElementById("content");
    var loading = document.getElementById("loading");
 
    window.history.replaceState(
        {
            content:content.innerHTML,
            page:page
        },
        page,
        urlbase + (page > 1 ? '?page=' + page : '' )
    );
 
    var ajax = new XMLHttpRequest();
    var ajaxCallback = function(){
        if(ajax.readyState == 4){
            loading.style.display = 'none';
            content.innerHTML = ajax.responseText;
            window.history.pushState(
                {
                    content:content.innerHTML,
                    page:page
                },
                page,
                urlbase + "?page=" + page
            );
            next.href = urlbase + "?page=" + (page + 1);
        }
    };
 
    var next = document.getElementById('next');
    var nextClickEvent = function(event){
        if(loading.style.display != 'block'){
            loading.style.display = 'block';
            page++;
            ajax.open('GET', urlbase + '?page=' + page + '&ajaxload=on', true);
            ajax.onreadystatechange = ajaxCallback;
            ajax.send('');
            event.preventDefault();
        }
    };
    next.addEventListener('click', nextClickEvent, false);
 
    var popstate = function(){
        content.innerHTML = history.state.content;
        page = history.state.page;
    };
    window.addEventListener('popstate', popstate, false);
};
 
try{
    window.addEventListener('DOMContentLoaded', domLoaded, false);
}
catch(e){
    alert('您的瀏覽器不支持');    
}
</script>
</head>
<body>
    <p id="content">
        <?php echo "第{$page}頁(yè)的內(nèi)容";?>
    </p>
    <p>
        <a id="next" href="?page=<?php echo $page+1;?>">下一頁(yè)</a>
    </p>
    <div id="loading" style="display:none;">
        加載中
    </div>
</body>
</html>
mozilla的文檔
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
stackoverflow上的相關(guān)問(wèn)題:
http://stackoverflow.com/questions/3338642/updating-address-bar-with-new-url-without-hash-or-reloading-the-page
http://stackoverflow.com/questions/824349/modify-the-url-without-reloading-the-page

小馬歌 2012-03-16 15:18 發(fā)表評(píng)論
]]>
提升用戶體驗(yàn):HTML5 拖放文件上傳【轉(zhuǎn)】http://www.tkk7.com/xiaomage234/archive/2012/03/08/371525.html小馬歌小馬歌Thu, 08 Mar 2012 05:57:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/08/371525.htmlhttp://www.tkk7.com/xiaomage234/comments/371525.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/08/371525.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/371525.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/371525.html話說(shuō),還是有不少項(xiàng)目里提供讓用戶上傳東西的。小到一個(gè) wordpress 博客,大到一個(gè)文件存儲(chǔ)網(wǎng)站。為了更好的用戶體驗(yàn)。來(lái)學(xué)習(xí)兩個(gè)新知識(shí)吧。HTML5 文件訪問(wèn)(File Access: FileReader)和拖放(Drag and Drop)。或許下個(gè)項(xiàng)目就能用上了。

一、起因

minus

今天看到 twitter 上有人在分享 Min.us 這個(gè)網(wǎng)站。說(shuō)是只要把圖片進(jìn)去,就可以分享。是的,它確實(shí)是這樣。體驗(yàn)了一翻,無(wú)論從界面,還操作的方便性上說(shuō),這體驗(yàn)還真是很贊的。

不過(guò),我更在意的是,他用了什么樣的技術(shù)。想著今晚回來(lái)瞄下代碼。這下,汗的事來(lái)了。這頁(yè)面看起來(lái)不像前端寫的啊。亂七八糟的。真是看不下去了。不過(guò),為了更好的用戶體驗(yàn),看吧。從頁(yè)面的 HTML5 標(biāo)簽猜測(cè)到可能用到 HTML5 的某些 API,再查一下 JS 發(fā)現(xiàn)了這兩行:

function isValidBrowser() {   var browser = BrowserDetect.browser;   var version = BrowserDetect.version;   var OS = BrowserDetect.OS;   //alert(browser+','+version+','+OS);   return (     (browser == 'Chrome' && version >= 6) ||     (browser == 'Firefox' && version >= 3.6) || 	(browser == 'Safari' && version >= 5.0 && OS == 'Mac') ||     ("FileReader" in self && "ondrag" in document)   ); } 

二、DEMO

先來(lái)個(gè)預(yù)覽吧,你可以先玩玩,再接著往下面看:HTML5 文件拖放上傳

三、如何實(shí)現(xiàn)

好吧,確定是使用HTML5。我們來(lái)看一下這種技術(shù)是怎么實(shí)現(xiàn)的吧。嗯,再回看上面的代碼,還有我提了這么多次,其實(shí),它就用到兩個(gè)技術(shù):

  1. FileReader,HTML5 File API
  2. Drag and Drop,似乎IE從 5.5 就支持了,都不敢說(shuō)她是 HTML5 了

這里有兩篇比較詳細(xì)的文章,看(等看完我講的,你再去看吧):

  1. Native HTML5 Drag and Drop
  2. Reading local files in JavaScript

現(xiàn)在 1:10 am 了,同學(xué)。明天還要上班。而具體講來(lái),還是需要很多時(shí)間滴。我們就簡(jiǎn)單一點(diǎn)。說(shuō)些應(yīng)該注意的吧。具體的實(shí)現(xiàn),你看我 DEMO 的代碼吧,和上面的文章吧。

一、 瀏覽器檢測(cè) & 支持

支持的瀏覽器并不多,我測(cè)試的是 Filefox 和 Chrome, winSafari 5.0.2 沒(méi)通過(guò)。IE8 以下就更不用說(shuō)了,當(dāng)然,Opera 也沒(méi)有支持。

if (window.FileReader) { 	// 做事的 } else { 	alert('你的瀏覽器不支持啊,同學(xué)') } 

從 Minus 的代碼中可以看出,支持的有:

  1. Chrome 6+
  2. Firefox 3.6+
  3. Mac Safari 5.0+

其他的,就是浮云了。不過(guò),這已經(jīng)足夠了,因?yàn)槲覀兛梢杂?hack 來(lái)實(shí)現(xiàn)。我們這里,就講可以用的吧。不可以的,就用原來(lái)項(xiàng)目中使用的方法吧。

二、注意事項(xiàng)

  1. 瀏覽器默認(rèn)行為

    默認(rèn)情況下,你向 Firefox 拖進(jìn)一張圖片,他可能會(huì)重定向于新頁(yè)面。或者拖過(guò)一個(gè)鏈接,可能會(huì)讓頁(yè)面重定向。我想,你一定不會(huì)讓你的用戶一邊上傳,一邊又打開(kāi)一個(gè)本地文件頁(yè)面,然后讓他再跑回來(lái)上傳的頁(yè)面。那就,阻止瀏覽器默認(rèn)行為是非常有必要的。

  2. 事件綁定

    你可能發(fā)現(xiàn)了,在 DEMO 當(dāng)我們把東西拖進(jìn)容器的時(shí)候,容器的邊框樣式變成虛線。因?yàn)槲疫@里綁定了一個(gè)事件,當(dāng)文件進(jìn)入目標(biāo)是,添加一個(gè) dragenter 的 CLASSNAME。這里需要注意的事,減少事件的解法,你可以在事件 ondragenter 的時(shí)候,添加 CLASSNAME ,而 ondragleave 的時(shí)候,刪除 CLASSNAME。但綁定在 dragover 上,他就像 mouseover ,在拖動(dòng)的過(guò)程中不斷解發(fā),這對(duì)于瀏覽器的負(fù)擔(dān)就很大了。可能會(huì)導(dǎo)致一些亂七八糟的,類似于崩潰之類的事。

  3. dataTransfer 的格式

    你可能需要用 e.dataTransfer.setData 和 e.dataTransfer.getData 來(lái)決定是否上傳用戶拖放的文件。

  4. File API 的狀態(tài)和 result

    檢測(cè)狀態(tài),以便下一步操作,而 result 則可以實(shí)現(xiàn)本地預(yù)覽的功能,讓用戶知道自己要上傳的東西是什么。

  5. File API 的讀取格式
    • FileReader.readAsBinaryString(fileBlob) -  result 屬性會(huì)包含一個(gè)文件的二進(jìn)制的格式
    • FileReader.readAsText(fileBlob, opt_encoding) -  result屬性將會(huì)包含一個(gè)文件的文本格式,默認(rèn)解碼參數(shù)是 “utf-8”。
    • FileReader.readAsDataURL(file) -  result 將會(huì)包含一個(gè)文件的 DataURL 格式(圖片通常用這種方式)

四、具體的應(yīng)用

其實(shí)我還沒(méi)有見(jiàn)到國(guó)內(nèi)用上這個(gè)技術(shù)的網(wǎng)站。剛才瞄了一下 QQ 微博。也沒(méi)有。對(duì)于這些新技術(shù)。于我們前端開(kāi)來(lái),其實(shí)挑戰(zhàn)并不是會(huì)不會(huì)使用,而是,如何去使用。

比如,在支付寶,下次需要改版用戶上傳身份證認(rèn)證的時(shí)候,或許我會(huì)去推動(dòng)這樣的改進(jìn)。又比如,如果是我在做 QQ 微博,或者任何一個(gè)微博,我將會(huì)提供一個(gè)讓用戶拖讓一張圖片就能上傳的功能。

HTML5 能用到的地方太多了。就慢你沒(méi)想法。因?yàn)閯e人其實(shí)并不清楚,連最清楚的你,前端,都不去推動(dòng),還能有誰(shuí)去推動(dòng)呢?

好吧。在接下來(lái)的項(xiàng)目中,你,或許也可以試試。



小馬歌 2012-03-08 13:57 發(fā)表評(píng)論
]]>
推薦一些采用html5技術(shù),支持直接拖拽上傳的網(wǎng)盤http://www.tkk7.com/xiaomage234/archive/2012/03/08/371524.html小馬歌小馬歌Thu, 08 Mar 2012 05:56:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/08/371524.htmlhttp://www.tkk7.com/xiaomage234/comments/371524.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/08/371524.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/371524.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/371524.html跟著html5手藝的不竭成熟,越來(lái)越多的應(yīng)用采用html5手藝,html5的一項(xiàng)吸惹人的功能之一就是能夠從桌面直接拖拽文件就可以上傳,很是便利,國(guó)外已經(jīng)有幾個(gè)網(wǎng)盤采用了這一手藝,這里為巨匠介紹幾個(gè),當(dāng)然使用這一功能需要你的瀏覽器撐持html5手藝。


  1.Let's Crate


  Let's Crate,采用了較新的手藝,拖曳就能快速上傳文件(但需要瀏覽器的撐持,建議使用谷歌瀏覽器)的一款國(guó)外網(wǎng)盤,簡(jiǎn)單易用,它不需要注冊(cè),打開(kāi)頁(yè)面后,直接把要上傳的文件拖曳到頁(yè)面中心的木箱里,完成后,會(huì)生成文件分享鏈接。還有它會(huì)提醒你注冊(cè)一個(gè)帳戶。若是不想注冊(cè),那么復(fù)制分享鏈接,但只能使用30 分鐘,相當(dāng)于的用于姑且分享的,建議注冊(cè),注冊(cè)后可以看到你今朝成立的文件夾數(shù)、上傳文件總數(shù)以及可使用的空間,今朝免費(fèi)帳戶可以使用的容量為 200MB。


  網(wǎng)址:


  http://www.letscrate.com/


  2.Ge.tt


  Ge.tt,一個(gè)設(shè)計(jì)精練清雅文件存儲(chǔ)分享網(wǎng)盤,上傳速度很快。它最年夜的特點(diǎn)在于上傳存儲(chǔ)分享極其精練便捷,就跟它精練的域名一樣,Ge.tt頁(yè)面只有一個(gè)精明的上傳文件的按鈕。


  它為你供給無(wú)限量的收集空間,免費(fèi)用戶撐持保留文件30天,撐持批量上傳,可是是經(jīng)由過(guò)程一路選擇當(dāng)?shù)囟鄠€(gè)文件上傳,不需要你一個(gè)一個(gè)添加文件,一次最多可以上傳30個(gè),上傳完成后系統(tǒng)會(huì)供給超短分享外鏈地址,也供給一鍵分享到Facebook和Twitter,當(dāng)你的鼠標(biāo)滑過(guò)此鏈接時(shí)可復(fù)制該鏈接與你的伴侶分享。


  此外,您還可以經(jīng)由過(guò)程注冊(cè)獲得額外功能,如對(duì)下載次數(shù)的實(shí)時(shí)統(tǒng)計(jì)、更長(zhǎng)久的文件保留時(shí)刻。


  網(wǎng)址:http://www.ge.tt/


  3..Min.us


  Min.us,帶給你全新上傳體驗(yàn)在線圖片存儲(chǔ),瀏覽,分享和打點(diǎn)工具。頁(yè)面很是精練,您只需把圖片拖拽到Min.us的頁(yè)面里,圖片就能自動(dòng)上傳。若是想成批上傳圖片,只需用鼠標(biāo)拔取多張一塊拖拽到Min.us即可。要考試考試此項(xiàng)功能,必需你的瀏覽器是Firefox 3.6+, Chrome, Safari, IE9瀏覽器。否則,會(huì)呈現(xiàn)指定文件上傳的上傳頁(yè)面。圖片上傳后Min.us會(huì)自動(dòng)完成而且生成相冊(cè)鏈接,便利您分享給伴侶,有作為編纂用(Edit)鏈接,有用來(lái)分享的(Viewer)鏈接。在每個(gè)圖片正下方有一個(gè)鏈接(Link to image)便利你將上傳后的圖片貼到任何網(wǎng)站和博客中。


  今朝Min.us撐持上傳的圖片名目有:JPEG, JPG, GIF, PNG, APNG,BMP。撐持單張7MB以下的圖片上傳,每個(gè)相冊(cè)圖片不跨越50張,上傳的圖片是永遠(yuǎn)保留的。


  網(wǎng)址:http://min.us/


  4.PicsEngine


  PicsEngine,一款在線圖片打點(diǎn)存儲(chǔ)軟件,近似與桌面版的picasa,你也可以將它算作專注于圖片存儲(chǔ)的網(wǎng)盤。PicsEngine打點(diǎn)照片很是便利輕易,供給使用標(biāo)簽來(lái)智能打點(diǎn)相冊(cè)。它的整體界面設(shè)計(jì)很是酷的,供給了無(wú)限的存儲(chǔ)空間,而且可以從任何處所來(lái)進(jìn)行訪謁。


  PicsEngine有一個(gè)強(qiáng)年夜的很新的功能,就是你可以直接從桌面拖動(dòng)照片到瀏覽器進(jìn)行上傳,當(dāng)然體驗(yàn)這一功能你需要安裝較高版本的網(wǎng)頁(yè)瀏覽器



小馬歌 2012-03-08 13:56 發(fā)表評(píng)論
]]>
HTML5文件實(shí)現(xiàn)拖拽上傳【轉(zhuǎn)】http://www.tkk7.com/xiaomage234/archive/2012/03/07/371390.html小馬歌小馬歌Wed, 07 Mar 2012 04:32:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/03/07/371390.htmlhttp://www.tkk7.com/xiaomage234/comments/371390.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/03/07/371390.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/371390.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/371390.html閱讀全文

小馬歌 2012-03-07 12:32 發(fā)表評(píng)論
]]>
[情人節(jié)專屬]純js腳本1k大小的3D玫瑰http://www.tkk7.com/xiaomage234/archive/2012/02/10/369728.html小馬歌小馬歌Fri, 10 Feb 2012 03:59:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/02/10/369728.htmlhttp://www.tkk7.com/xiaomage234/comments/369728.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/02/10/369728.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/369728.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/369728.html

導(dǎo)語(yǔ):前年圣誕節(jié)上,西班牙程序員Roman Cortes帶來(lái)了用純javascript腳本編寫的神奇3D圣誕樹(shù),令人印象深刻。2月14日情人節(jié)就要來(lái)臨了,還是Roman Cortes,這次他又帶來(lái)了用javascript腳本編寫的紅色玫瑰花。用代碼做出的玫瑰花,這才是牛逼程序員送給女友的最好情人節(jié)禮物呢!(提示:在不同瀏覽器下觀看效果、速度會(huì)有很大的不同)








圖片是由代碼生成,用戶可以刷新該頁(yè)面,重復(fù)觀看這朵玫瑰的呈現(xiàn)過(guò)程。

3D玫瑰花的實(shí)現(xiàn)代碼如下:

with(m=Math)C=cos,S=sin,P=pow,R=random;c.width=c.height=f=500;h=-250;function p(a,b,c){if(c>60)return[S(a*7)*(13+5/(.2+P(b*4,4)))-S(b)*50,b*f+50,625+C(a*7)*(13+5/(.2+P(b*4,4)))+b*400,a*1-b/2,a];A=a*2-1;B=b*2-1;if(A*A+B*B<1){if(c>37){n=(j=c&1)?6:4;o=.5/(a+.01)+C(b*125)*3-a*300;w=b*h;return[o*C(n)+w*S(n)+j*610-390,o*S(n)-w*C(n)+550-j*350,1180+C(B+A)*99-j*300,.4-a*.1+P(1-B*B,-h*6)*.15-a*b*.4+C(a+b)/5+P(C((o*(a+1)+(B>0?w:-w))/25),30)*.1*(1-B*B),o/1e3+.7-o*w*3e-6]}if(c>32){c=c*1.16-.15;o=a*45-20;w=b*b*h;z=o*S(c)+w*C(c)+620;return[o*C(c)-w*S(c),28+C(B*.5)*99-b*b*b*60-z/2-h,z,(b*b*.3+P((1-(A*A)),7)*.15+.3)*b,b*.7]}o=A*(2-b)*(80-c*2);w=99-C(A)*120-C(b)*(-h-c*4.9)+C(P(1-b,7))*50+c*2;z=o*S(c)+w*C(c)+700;return[o*C(c)-w*S(c),B*99-C(P(b, 7))*50-c/3-z/1.35+450,z,(1-b/1.2)*.9+a*.1, P((1-b),20)/4+.05]}}setInterval('for(i=0;i<1e4;i++)if(s=p(R(),R(),i%46/.74)){z=s[2];x=~~(s[0]*f/z-h);y=~~(s[1]*f/z-h);if(!m[q=y*f+x]|m[q]>z)m[q]=z,a.fillStyle="rgb("+~(s[3]*h)+","+~(s[4]*h)+","+~(s[3]*s[3]*-80)+")",a.fillRect(x,y,1,1)}',0)

當(dāng)然,感興趣的人可以了解下面的實(shí)現(xiàn)過(guò)程與相關(guān)理論:

這朵三維代碼玫瑰的呈現(xiàn)效果采用了蒙特卡羅方法,創(chuàng)造者對(duì)蒙特卡羅方法非常推崇,他表示在功能優(yōu)化和采樣方面,蒙特卡羅方法是“令人難以置信的強(qiáng)大工具”。關(guān)于蒙特卡羅方法可以參考:Monte Carlo method 。

具體操作:

外觀采樣呈現(xiàn)效果繪制

我用了多個(gè)不同的形狀圖來(lái)組成這朵代碼玫瑰。共使用了31個(gè)形狀:24個(gè)花瓣,4個(gè)萼片,2個(gè)葉子和1根花莖,其中每一個(gè)形狀圖都用代碼進(jìn)行描繪。

首先,來(lái)定義一個(gè)采樣范圍:

function surface(a, b) { // I'm using a and b as parameters ranging from 0 to 1.

return {

x: a*50,

y: b*50

};

// this surface will be a square of 50x50 units of size

}

然后,編寫形狀描繪代碼:

var canvas = document.body.appendChild(document.createElement("canvas")),

context = canvas.getContext("2d"),

a, b, position;

// Now I'm going to sample the surface at .1 intervals for a and b parameters:

for (a = 0; a < 1; a += .1) {

for (b = 0; b < 1; b += .1) {

position = surface(a, b);

context.fillRect(position.x, position.y, 1, 1);

}

}

這時(shí),看到的效果是這樣的:

現(xiàn)在,嘗試一下更密集的采樣間隔:

正如現(xiàn)在所看到的,因?yàn)椴蓸娱g隔越來(lái)越密集,點(diǎn)越來(lái)越接近,到最高密度時(shí),相鄰點(diǎn)之間的距離小于一個(gè)像素,肉眼就看不到間隔(見(jiàn)0.01)。為了不造成太大的視覺(jué)差,再進(jìn)一步縮小采樣間隔,此時(shí),繪制區(qū)已經(jīng)填滿(比較結(jié)果為0.01和0.001)。

接下來(lái),我用這個(gè)公式來(lái)繪制一個(gè)圓形:(X-X0)^ 2 +(Y-Y0)^ 2 <半徑^ 2,其中(X0,Y0)為圓心:

function surface(a, b) {

var x = a * 100,

y = b * 100,

radius = 50,

x0 = 50,

y0 = 50;

if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {

// inside the circle

return {

x: x,

y: y

};

} else {

// outside the circle

return null;

}

}

為了防止溢出,還要加上一個(gè)采樣條件:

if (position = surface(a, b)) {

context.fillRect(position.x, position.y, 1, 1);

}

結(jié)果如下:

有不同的方法來(lái)定義一個(gè)圓,其中一些并不需要拒絕采樣。我并無(wú)一定要使用哪一種來(lái)定義圓圈的意思,所以下面用另一種方法來(lái)定義一個(gè)圓:

function surface(a, b) {

// Circle using polar coordinates

var angle = a * Math.PI * 2,

radius = 50,

x0 = 50,

y0 = 50;

return {

x: Math.cos(angle) * radius * b + x0,

y: Math.sin(angle) * radius * b + y0

};

}

如圖:

(此方法相比前一個(gè)方法需要密集采樣以進(jìn)行填充。)

好了,現(xiàn)在讓圓變形,以使它看起來(lái)更像是一個(gè)花瓣:

function surface(a, b) {

var x = a * 100,

y = b * 100,

radius = 50,

x0 = 50,

y0 = 50;

if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {

return {

x: x,

y: y * (1 + b) / 2 // deformation

};

} else {

return null;

}

}

結(jié)果:

這看起來(lái)已經(jīng)很像一個(gè)玫瑰花瓣的形狀了。在這里也可以試試通過(guò)修改一些函數(shù)數(shù)值,將會(huì)出現(xiàn)很多有趣的形狀。

接下來(lái)應(yīng)該給它添加色彩了:

function surface(a, b) {

var x = a * 100,

y = b * 100,

radius = 50,

x0 = 50,

y0 = 50;

if ((x - x0) * (x - x0) + (y - y0) * (y - y0) < radius * radius) {

return {

x: x,

y: y * (1 + b) / 2,

r: 100 + Math.floor((1 - b) * 155), // this will add a gradient

g: 50,

b: 50

};

} else {

return null;

}

}

for (a = 0; a < 1; a += .01) {

for (b = 0; b < 1; b += .001) {

if (point = surface(a, b)) {

context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";

context.fillRect(point.x, point.y, 1, 1);

}

}

}

結(jié)果:

一片帶色的花瓣就出現(xiàn)了。

3D曲面和透視投影

定義三維表面很簡(jiǎn)單,比如,來(lái)定義一個(gè)管狀物體:

function surface(a, b) {

var angle = a * Math.PI * 2,

radius = 100,

length = 400;

return {

x: Math.cos(angle) * radius,

y: Math.sin(angle) * radius,

z: b * length - length / 2, // by subtracting length/2 I have centered the tube at (0, 0, 0)

r: 0,

g: Math.floor(b * 255),

b: 0

};

}

接著添加投影透視圖,首先需要我們定義一個(gè)攝像頭:

如上圖,將攝像頭放置在(0,0,Z)位置,畫布在X / Y平面。投影到畫布上的采樣點(diǎn)為:

var pX, pY, // projected on canvas x and y coordinates

perspective = 350,

halfHeight = canvas.height / 2,

halfWidth = canvas.width / 2,

cameraZ = -700;

for (a = 0; a < 1; a += .001) {

for (b = 0; b < 1; b += .01) {

if (point = surface(a, b)) {

pX = (point.x * perspective) / (point.z - cameraZ) + halfWidth;

pY = (point.y * perspective) / (point.z - cameraZ) + halfHeight;

context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";

context.fillRect(pX, pY, 1, 1);

}

}

}

效果為:

z-buffer

z-buffer在計(jì)算機(jī)圖形學(xué)中是一個(gè)相當(dāng)普遍的技術(shù),在為物件進(jìn)行著色時(shí),執(zhí)行“隱藏面消除”工作,使隱藏物件背后的部分就不會(huì)被顯示出來(lái)。

上圖是用z-buffer技術(shù)處理后的玫瑰。(可以看到已經(jīng)具有立體感了)

代碼如下:

var zBuffer = [],

zBufferIndex;

for (a = 0; a < 1; a += .001) {

for (b = 0; b < 1; b += .01) {

if (point = surface(a, b)) {

pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);

pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);

zBufferIndex = pY * canvas.width + pX;

if ((typeof zBuffer[zBufferIndex] === "undefined") || (point.z < zBuffer[zBufferIndex])) {

zBuffer[zBufferIndex] = point.z;

context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";

context.fillRect(pX, pY, 1, 1);

}

}

}

}

旋轉(zhuǎn)

你可以使用任何矢量旋轉(zhuǎn)的方法。在代碼玫瑰的創(chuàng)建中,我使用的是歐拉旋轉(zhuǎn)。現(xiàn)在將之前編寫的管狀物進(jìn)行旋轉(zhuǎn),實(shí)現(xiàn)繞Y軸旋轉(zhuǎn):

function surface(a, b) {

var angle = a * Math.PI * 2,

radius = 100,

length = 400,

x = Math.cos(angle) * radius,

y = Math.sin(angle) * radius,

z = b * length - length / 2,

yAxisRotationAngle = -.4, // in radians!

rotatedX = x * Math.cos(yAxisRotationAngle) + z * Math.sin(yAxisRotationAngle),

rotatedZ = x * -Math.sin(yAxisRotationAngle) + z * Math.cos(yAxisRotationAngle);

return {

x: rotatedX,

y: y,

z: rotatedZ,

r: 0,

g: Math.floor(b * 255),

b: 0

};

}

效果:

蒙特卡羅方法

關(guān)于采樣時(shí)間,間隔過(guò)大過(guò)小都會(huì)引起極差的視覺(jué)感受,所以,需要設(shè)置合理的采樣間隔,這里使用蒙特卡羅方法。

var i;

window.setInterval(function () {

for (i = 0; i < 10000; i++) {

if (point = surface(Math.random(), Math.random())) {

pX = Math.floor((point.x * perspective) / (point.z - cameraZ) + halfWidth);

pY = Math.floor((point.y * perspective) / (point.z - cameraZ) + halfHeight);

zBufferIndex = pY * canvas.width + pX;

if ((typeof zBuffer[zBufferIndex] === "undefined") || (point.z < zBuffer[zBufferIndex])) {

zBuffer[zBufferIndex] = point.z;

context.fillStyle = "rgb(" + point.r + "," + point.g + "," + point.b + ")";

context.fillRect(pX, pY, 1, 1);

}

}

}

}, 0);

設(shè)置a和b為隨機(jī)參數(shù),用足夠的采樣完成表面填充。我每次繪制10000點(diǎn),然后靜待屏幕完成更新。

另外需要注意的是,如果隨機(jī)數(shù)發(fā)生錯(cuò)誤時(shí),表面填充效果會(huì)出錯(cuò)。有些瀏覽器中,Math.random的執(zhí)行是線性的,這就有可能導(dǎo)致表面填充效果出錯(cuò)。這時(shí),就得使用類似Mersenne Twister(一種隨機(jī)數(shù)算法)這樣的東西去進(jìn)行高質(zhì)量的PRNG采樣,從而避免錯(cuò)誤的發(fā)生。

完成

為了使玫瑰的每個(gè)部分在同一時(shí)間完成并呈現(xiàn),還需要添加一個(gè)功能,為每部分設(shè)置一個(gè)參數(shù)以返回值來(lái)進(jìn)行同步。并用一個(gè)分段函數(shù)代表玫瑰的各個(gè)部分。比如在花瓣部分,我用旋轉(zhuǎn)和變形來(lái)創(chuàng)建它們。

雖然表面采樣方法是創(chuàng)建三維圖形非常著名的、最古老的方法之一,但這種把蒙特卡羅、z-buffer加入到表面采樣中的方法并不常見(jiàn)。對(duì)于現(xiàn)實(shí)生活場(chǎng)景的制作,這也許算不上很有創(chuàng)意,但它簡(jiǎn)易的代碼實(shí)現(xiàn)和很小的體積仍令人滿意。

希望這篇文章能激發(fā)計(jì)算機(jī)圖形學(xué)愛(ài)好者來(lái)嘗試不同的呈現(xiàn)方法,并從中獲得樂(lè)趣。(Roman Cortes)

英文原址:romancortes.com 



小馬歌 2012-02-10 11:59 發(fā)表評(píng)論
]]>
HTML5在Android iOS等移動(dòng)平臺(tái)上的兼容性http://www.tkk7.com/xiaomage234/archive/2012/02/09/369682.html小馬歌小馬歌Thu, 09 Feb 2012 08:07:00 GMThttp://www.tkk7.com/xiaomage234/archive/2012/02/09/369682.htmlhttp://www.tkk7.com/xiaomage234/comments/369682.htmlhttp://www.tkk7.com/xiaomage234/archive/2012/02/09/369682.html#Feedback0http://www.tkk7.com/xiaomage234/comments/commentRss/369682.htmlhttp://www.tkk7.com/xiaomage234/services/trackbacks/369682.html閱讀全文

小馬歌 2012-02-09 16:07 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 亚洲天堂在线播放| 无码av免费网站| 国产免费观看网站| 亚洲综合激情五月色一区| 69视频免费观看l| 亚洲成人在线网站| 日韩电影免费在线观看| 亚洲中文字幕日产乱码高清app| 视频一区二区三区免费观看| 真实乱视频国产免费观看| 亚洲熟妇AV一区二区三区浪潮| 成年人网站免费视频| 亚洲老熟女@TubeumTV| 免费无遮挡无码永久视频 | 亚洲精品第一国产综合精品| 日本免费在线观看| 亚洲成AV人片在线观看无| 成人免费无码H在线观看不卡| 亚洲精品国产V片在线观看| 黄色免费网址大全| 亚洲AV无码成H人在线观看| 边摸边吃奶边做爽免费视频网站 | 国产黄色免费网站| 亚洲精品国产专区91在线| 曰批视频免费40分钟试看天天| 亚洲无线电影官网| 13一14周岁毛片免费| 亚洲综合男人的天堂色婷婷| 91精品国产免费| 亚洲成综合人影院在院播放| 亚洲精品国产免费| 亚洲人成7777| 国内外成人免费视频| 亚洲AV无码AV吞精久久| 免费在线观看日韩| 一级毛片免费播放男男| 亚洲中久无码永久在线观看同| 国产免费一区二区三区在线观看| 亚洲va久久久噜噜噜久久男同| 91成人在线免费视频| 亚洲粉嫩美白在线|