1. 程式人生 > >超實用的HTML 5介面全方位測試總結文

超實用的HTML 5介面全方位測試總結文

tgideas-html5-api-test-1-1

編者按:今天騰訊萬技師同學的這篇技術總結必須強烈安利下,目錄清晰,層次分明,每個介面都有對應的簡介、系統要求、例項、核心程式碼以及超實用的思維發散,幫你直觀把這些知識點get起來。以現在HTML 5的勢頭,同志們,你看到的這些,可都是錢吶。

十二年前,無論多麼複雜的佈局,在我們神奇的table面前,都不是問題;

十年前,阿捷的一本《網站重構》,為我們開啟了新的篇章;

八年前,我們研究yahoo.com,驚歎它在IE5下都表現得如此完美;

六年前,Web標準化成了我們的基礎技能,我們開始研究網站效能優化;

四年前,我們開始研究自動化工具,自動化測試,誰沒玩過nodejs都不好意思說是頁面仔;

二年前,各種終端風起雲湧,響應式、APP開發都成為了我們研究的範圍,CSS3動畫開始風靡;

如今,CSS3動畫、Canvas、SVG、甚至webGL你已經非常熟悉,你是否開始探尋,接下來,我們可以玩什麼,來為我們專案帶來一絲新意?

沒錯,本文就是以HTML5 Device API為核心,對HTML5的一些新介面作了一個完整的測試,希望能讓大家有所啟發。

目錄:

一、讓音樂隨心而動 – 音訊處理 Web audio API
二、捕捉使用者攝像頭 – 媒體流 Media Capture
三、你是逗逼? – 語音識別 Web Speech API
四、讓我盡情呵護你 – 裝置電量 Battery API
五、獲取使用者位置 – 地理位置 Geolocation API
六、把使用者捧在手心 – 環境光 Ambient Light API
七、陀螺儀 Deviceorientation
八、Websocket
九、NFC
十、震動 – Vibration API
十一、網路環境 Connection API

一、讓音樂隨心而動 – 音訊處理 Web audio API

簡介:

Audio物件提供的只是音訊檔案的播放,而Web Audio則是給了開發者對音訊資料進行分析、處理的能力,比如混音、過濾。

系統要求:

ios6+、android chrome、android firefox

例項:

核心程式碼:

var context = new webkitAudioContext();
var source = context.createBufferSource();   // 建立一個聲音源
source.buffer = buffer;   // 告訴該源播放何物 
createBufferSourcesource.connect(context.destination);   // 將該源與硬體相連
source.start(0); //播放

技術分析:

當我們載入完音訊資料後,我們將建立一個全域性的AudioContext物件來對音訊進行處理,AudioContext可以建立各種不同功能型別的音訊節點AudioNode,比如

1、源節點(source node)

我們可以使用兩種方式載入音訊資料:
<1>、audio標籤

var sound, audio = new Audio();
audio.addEventListener('canplay', function() {
 sound = context.createMediaElementSource(audio);
 sound.connect(context.destination);
});
audio.src = '/audio.mp3';

<2>、XMLHttpRequest

var sound, context = createAudioContext();
var audioURl = '/audio.mp3'; // 音訊檔案URL
var xhr = new XMLHttpRequest();
xhr.open('GET', audioURL, true);
xhr.responseType = 'arraybuffer'; 
xhr.onload = function() {
 context.decodeAudioData(request.response, function (buffer) {
 source = context.createBufferSource();
 source.buffer = buffer;
 source.connect(context.destination);
 }
}
xhr.send();

2、分析節點(analyser node)

我們可以使用AnalyserNode來對音譜進行分析,例如:

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);

function draw() {
 drawVisual = requestAnimationFrame(draw);
 analyser.getByteTimeDomainData(dataArray);
 // 將dataArray資料以canvas方式渲染出來
};

draw();

3、處理節點(gain node、panner node、wave shaper node、delay node、convolver node等)

不同的處理節點有不同的作用,比如使用BiquadFilterNode調整音色(大量濾波器)、使用ChannelSplitterNode分割左右聲道、使用GainNode調整增益值實現音樂淡入淡出等等。

4、目的節點(destination node)

所有被渲染音訊流到達的最終地點

思維發散:

1、可以讓CSS3動畫跟隨背景音樂舞動,可以為我們的網頁增色不少;
2、可以嘗試製作H5酷酷的變聲應用,增加與使用者的互動;
3、甚至可以嘗試H5音樂創作。

二、捕捉使用者攝像頭 – 媒體流 Media Capture

簡介:

通過getUserMedia捕捉使用者攝像頭獲取視訊流和通過麥克風獲取使用者聲音。

系統要求:

android chrome、android firefox

例項:

捕獲使用者攝像頭 捕獲使用者麥克風

核心程式碼:

1、攝像頭捕捉

navigator.webkitGetUserMedia ({video: true}, function(stream) {
 video.src = window.URL.createObjectURL(stream);
 localMediaStream = stream;
}, function(e){

})

2、從視訊流中拍照

btnCapture.addEventListener('touchend', function(){
	if (localMediaStream) {
		canvas.setAttribute('width', video.videoWidth);
		canvas.setAttribute('height', video.videoHeight);
		ctx.drawImage(video, 0, 0);
	}
}, false);

3、使用者聲音錄製

navigator.getUserMedia({audio:true}, function(e) {
	context = new audioContext();
	audioInput = context.createMediaStreamSource(e);	
	volume = context.createGain();
	recorder = context.createScriptProcessor(2048, 2, 2);
	recorder.onaudioprocess = function(e){
		recordingLength += 2048;
		recorder.connect (context.destination); 
	}	
}, function(error){});

4、儲存使用者錄製的聲音

var buffer = new ArrayBuffer(44 + interleaved.length * 2);
var view = new DataView(buffer);
fileReader.readAsDataURL(blob); // android chrome audio不支援blob
… audio.src = event.target.result;

思維發散:

1、從視訊拍照自定義頭像;
2、H5視訊聊天;
3、結合canvas完成好玩的照片合成及處理;
4、結合Web Audio製作有意思變聲應用。

三、你是逗逼? – 語音識別 Web Speech API簡介:

1、將文字轉換成語音;
2、將語音識別為文字。

系統要求:
ios7+,android chrome,android firefox

測試例項:

核心程式碼:

1、文字轉換成語音,使用SpeechSynthesisUtterance物件;

var msg = new SpeechSynthesisUtterance();
var voices = window.speechSynthesis.getVoices();
msg.volume = 1; // 0 to 1
msg.text = ‘識別的文字內容’;
msg.lang = 'en-US';
speechSynthesis.speak(msg);

2、語音轉換為文字,使用SpeechRecognition物件。

var newRecognition = new webkitSpeechRecognition();
newRecognition.onresult = function(event){
	var interim_transcript = ''; 
	for (var i = event.resultIndex; i < event.results.length; ++i) {
		final_transcript += event.results[i][0].transcript;
	}
};

測試結論:

1、Android支援不穩定;語音識別測試失敗(暫且認為是某些內建介面被牆所致)。

思維發散:

1、當語音識別成為可能,那聲音控制將可以展示其強大的功能。在某些場景,比如開車、網路電視,聲音控制將大大改善使用者體驗;
2、H5遊戲中最終分數播報,股票資訊實時聲音提示,Web Speech都可以大放異彩。

 四、讓我盡情呵護你 – 裝置電量 Battery API簡介:

查詢使用者裝置電量及是否正在充電。

系統要求:

android firefox

測試例項:

核心程式碼:

var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery;
var str = '';
if (battery) {
 str += '<p>你的瀏覽器支援HTML5 Battery API</p>';
 if(battery.charging) {
 str += '<p>你的裝置正在充電</p>';
} else {
 str += '<p>你的裝置未處於充電狀態</p>';
}
 str += '<p>你的裝置剩餘'+ parseInt(battery.level*100)+'%的電量</p>';
} else {
 str += '<p>你的瀏覽器不支援HTML5 Battery API</p>';
}

測試結論:

1、QQ瀏覽器與UC瀏覽器支援該介面,但未正確顯示裝置電池資訊;
2、caniuse顯示android chrome42支援該介面,實測不支援。

思維發散:

相對而言,我覺得這個介面有些雞肋。
很顯然,並不合適用HTML5做電池管理方面的工作,它所提供的許可權也很有限。
我們只能嘗試做一些優化使用者體驗的工作,當用戶裝置電量不足時,進入省電模式,比如停用濾鏡、攝像頭開啟、webGL、減少網路請求等。

 五、獲取使用者位置 – 地理位置 Geolocation簡介:

Geolocation API用於將使用者當前地理位置資訊共享給信任的站點,目前主流移動裝置都能夠支援。

系統要求:

ios6+、android2.3+

測試例項:

核心程式碼:

var domInfo = $("#info");

// 獲取位置座標
if (navigator.geolocation) {
	navigator.geolocation.getCurrentPosition(showPosition,showError);
}
else{
	domInfo.innerHTML="抱歉,你的瀏覽器不支援地理定位!";
}

// 使用騰訊地圖顯示位置
function showPosition(position) {
	var lat=position.coords.latitude;
	var lon=position.coords.longitude;

	mapholder = $('#mapholder')
	mapholder.style.height='250px';
	mapholder.style.width = document.documentElement.clientWidth + 'px';

	var center = new soso.maps.LatLng(lat, lon);
	var map = new soso.maps.Map(mapholder,{
		center: center,
		zoomLevel: 13
	});

	var geolocation = new soso.maps.Geolocation();
	var marker = null;
	geolocation.position({}, function(results, status) {
		console.log(results);
		var city = $("#info");
		if (status == soso.maps.GeolocationStatus.OK) {
			map.setCenter(results.latLng);
			domInfo.innerHTML = '你當前所在城市: ' + results.name;
		if (marker != null) {
			marker.setMap(null);
		}
		// 設定標記
		marker = new soso.maps.Marker({
			map: map,
			position:results.latLng
		});
		} else {
			alert("檢索沒有結果,原因: " + status);
		}
	});
}

測試結論:

1、Geolocation API的位置資訊來源包括GPS、IP地址、RFID、WIFI和藍芽的MAC地址、以及GSM/CDMS的ID等等。規範中沒有規定使用這些裝置的先後順序。
2、初測3g環境下比wifi環境理定位更準確;
3、測試三星 GT-S6358(android2.3) geolocation存在,但顯示位置資訊不可用POSITION_UNAVAILABLE。

六、把使用者捧在手心 – 環境光 Ambient Light簡介:

Ambient Light API定義了一些事件,這些時間可以提供源於周圍光亮程度的資訊,這通常是由裝置的光感應器來測量的。裝置的光感應器會提取出輝度資訊。

系統要求:

android firefox

測試例項:

核心程式碼:

這段程式碼實現感應用前當前環境光強度,調整網頁背景和文字顏色。


var domInfo = $('#info');
if (!('ondevicelight' in window)) {
	domInfo.innerHTML = '你的裝置不支援環境光Ambient Light API';
} else {
	var lightValue = document.getElementById('dl-value');
	window.addEventListener('devicelight', function(event) {
		domInfo.innerHTML = '當前環境光線強度為:' + Math.round(event.value) + 'lux';
		var backgroundColor = 'rgba(0,0,0,'+(1-event.value/100) +')';
		document.body.style.backgroundColor = backgroundColor;
		if(event.value < 50) {
			document.body.style.color = '#fff'
		} else {
			document.body.style.color = '#000'
		}
	});
}

思維發散:

該介面適合的範圍很窄,卻能做出很貼心的使用者體驗。

1、當我們根據Ambient Light強度、陀螺儀資訊、當地時間判斷出使用者正躺在床上準備入睡前在體驗我們的產品,我們自然可以調整我們背景與文字顏色讓使用者感覺到舒適,我們還可以來一段安靜的音樂,甚至使用Web Speech API播報當前時間,並說一聲“晚安”,何其溫馨;

2、該介面也可以應用於H5遊戲場景,比如日落時分,我們可以在遊戲中使用安靜祥和的遊戲場景;

3、當用戶在工作時間將手機放在暗處,偷偷地瞄一眼股市行情的時候,我們可以用語音大聲播報,“親愛的,不用擔心,你的股票中國中車馬上就要跌停了”,多美的畫面。

那麼,各位看官起來搖一搖,活動活動筋骨,熱熱身。。。(PS:為什麼我會聯想到喝前搖一搖,吃(fan)貨(tong)天賦?)。

DeviceMotion:

簡介

裝逼說法:裝置移動感測器。

通俗說法:檢測裝置運動及運動狀況,可以通過該介面獲取到裝置運動的方向和速度等相關資訊

核心程式碼

這貨其實就是一個事件,簡單地通過事件監聽就可以獲取到相關的裝置運動資訊

window.addEventListener("devicemotion", function(event) {}, false);

最簡單的裝置運動,我們基本上可以認為是前後、左右、上下這麼6個方向上的,裝換成3D環境中來講的話,就是在x、y和z軸上運動,這三個軸上的資訊,都包含在了event物件中。我們可以通過這種方式獲得

window.addEventListener("devicemotion", function(event) {
    var eventacceleration = event.acceleration;
    document.querySelector('#devicemotion').innerHTML = "acceleration:<br>"+
    eventacceleration.x+"<br>"+
    eventacceleration.y+"<br>"+
    eventacceleration.z
}, false);

想看效果的話,這個時候就可以掏出手機,掃描下面的這個二維碼

1da7a7e95c64fcc2aa054a0ea2894ad51435222999.png

不要問我為什麼手機躺在桌面上,上面的數字還在不停地抖動,咱們文化人應該都知道什麼叫相對靜止。上面的三個不斷變化的數字,就是你裝置的運動資料了。如果你在驚訝為什麼我都已經移動過手機,為什麼上面的數字貌似也沒什麼大的變化~那麼我會告訴你說:有本事你的眼睛跟著你的手機一樣快速移動啊,運動過程中你就能發現這個值的變化了。沒有這個本事吧!~自己嘗試修改下那個demo。把運動中值的變化都記錄下來看看。。。(PS:反正我不弄。)

還有一種比較理想的裝置運動方式就是不產生位移,只是快速的旋轉手機。這個旋轉的資訊同樣也被反饋在了event物件中

window.addEventListener("devicemotion", function(event) {
    eventrotationRate = event.rotationRate;
    document.querySelector('#devicemotion').innerHTML = 'rotationRate:<br>'+
    eventrotationRate.alpha+'<br>'+
    eventrotationRate.beta+"<br>"+
    eventrotationRate.gamma
}, false);

同樣的,下面的二維碼也就是為了說明上面的這段程式碼,alpha、beta以及gamma就是旋轉裝置時的加速度。

1435214168_73_w177_h176.png

可能有的童鞋會覺得~有了這個旋轉應該就能實現一些手機左右旋轉產生視差的效果了,其實是不行的~因為這貨和上面的一樣,裝置停止後,我們可以認為他的值歸0~。真正想要實現手機旋轉視差,我們需要用到的就是另外一個event的屬性accelerationIncludingGravity。從字面上理解這個屬性就是重力加速度。

window.addEventListener("devicemotion", function(event) {
    eventaccelerationIncludingGravity = event.accelerationIncludingGravity;
    document.querySelector('#devicemotion').innerHTML = "accelerationIncludingGravity:<br>"+
    eventaccelerationIncludingGravity.x+"<br>"+
    eventaccelerationIncludingGravity.y+"<br>"+
    eventaccelerationIncludingGravity.z
}, false);

下面的這個二維碼應該可以幫助到你來理解這個屬性

1435215045_85_w176_h175.png

至此,devicemotion這個事件就差不多了,可見,這貨功能還是蠻強大的,如果你有一定的的數學和物理學的基礎,那麼,輕巧幾行程式碼,實現個高爾夫球遊戲玩玩,立馬給人感覺高大上了。看誰還敢說程式設計師沒有妹紙。。

通過這個devicemotion吧,還能實現些什麼就各自去腦洞大開吧,比如說玩爛了的搖一搖,裝置傾斜視差,重力感應類的小遊戲。我們貌似還能通過這個屬性,去做個基於HTML5的計步器玩玩?

其實,devicemotion還有一個好基友,這裡也推薦給大家看一眼吧:

deviceorientation

這個事件和devicemotion的使用方法基本一致

window.addEventListener("deviceorientation", function(event) {
    document.querySelector('#deviceorientation').innerHTML = 
    event.alpha+'<br>'+
    event.beta+"<br>"+
    event.gamma+'<br>';
}, false);

這裡的alpha、beta和gamma所指的就是手機裝置的各種傾斜角度,如果你不能理解哪個是alpha、哪個是beta和gamma,那麼你還是自己掏出手機,掃描下這個二維碼。自己感受吧。(PS:我是真不愛畫圖,可能辛苦半天畫出來的圖,也有童鞋沒明白)。

1435216564_27_w175_h176.png

有前面devicemotion好基友的幫忙,似乎能做的東西又可以更多一點了。咱們前面貌似提及過&ldquo;喝前搖一搖&rdquo;。搖完之後,自然是要開啟瓶蓋痛飲一番了,結合旋轉加速度,我們是不是可以嘗試些一個擰瓶蓋比賽的遊戲了?怕長胖?要不,擰個螺絲釘也行。

說到遊戲,特別上面還提及到了比賽。那麼實時通訊必然是不可少了。以往為了達到實時通訊,也有不少的方法:輪詢、長輪詢、長連線、flash等各種方式。這些方法各自的弊端也是比較明顯的,這裡就不逐個展開細說了。這裡主要給大家提交到的就是下面這貨:

webSocket

簡介

瀏覽器與伺服器全雙工通訊(full-duplex)。

核心程式碼

var ws = new WebSocket('ws://127.0.0.1:8808/');//建立伺服器連線ws.onopen = function(){
	systemInfo.innerHTML = '<p>和websocket伺服器連線成功</p>';
}//接收到伺服器返回的資料ws.onmessage = function(e){
	systemInfo.innerHTML += '<p>'+e.data+'</p>';
}//斷開伺服器連線ws.onclose = function(){
	systemInfo.innerHTML += '<p>WebSocket伺服器連線關閉</p>';
}//ws發生錯誤ws.onerror = function(e){
	console.log(e);
	systemInfo.innerHTML += '<p>WebSocket發生錯誤</p>';
}

websocket的資料傳送和接收,其實也都是依賴於網路的,webSocket自己也對網路狀況這塊通過事件的方式做出了相應,比如說上面的onclose、onerror。但是就目前來說,很多頁面上可能並沒有用webSocket,這麼一來,對於網路何時斷開了,可能捕獲就沒那麼容易了,更何況,webSocket在網路資訊這塊,可能還並不是那麼的完美。比如說,我想獲取當前連線的網路型別。

網路型別這塊我們暫且先放半分鐘,我們先看一下如何動態判斷網路連線是否斷開,所指動態判斷網路連線斷開,指的是,頁面不重新整理的情況下,實時地知道當前網路是否可用。以往,我們想得到這種資料,我們一般的實現方法是通過輪詢去訪問伺服器上的一個檔案,如果檔案正常響應,說明網路是通的;如果檔案不響應,那麼就認為網路是不通的。這種方式感覺挺靠譜,但是可以想象,輪詢請求,會耗費多少伺服器資源。下面這貨出來之後,以往的這種方式就可以進博物館了。

onLine

簡介:

判斷當前網路是否有效

用法也是相當地簡單:

if (navigator.onLine) {
    alert('online');
} else {
    alert('offline');
}

我們可以通過事件的監聽,去實時獲取到網路狀態的變化

window.addEventListener('offline', function(e) {alert('offline');})
window.addEventListener('online', function(e) {alert('online');})

這樣以來,實時獲取網路狀態儼然和伺服器已經沒有半毛錢關係了。

好了,半分鐘時間已到,我們回頭來看看我前面說的那個問題,獲取網路型別,所指網路型別,值的是2G、3G、4G、藍芽等等。其實,我個人覺得,這個網路型別完全可以放到online那個事件物件裡面去。但是很遺憾,至少目前沒放,暫不清楚是基於什麼考慮的。我們目前想要獲取這個網路型別,需要通過另外一個屬性

connection

connection也是navigator的一個屬性,他包含了一些當前連線的基本資訊,其中connection.type值的就是當前的網路型別。其值包含了一下幾個:

bluetooth  cellular  ethernet  none  wifi  wimax  wimax  unknown

當網路型別發生變化時,同樣的也是可以通過事件監聽的方式來實時獲取到網路型別。程式碼實現如下:

var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.type;
function updateConnectionStatus() {
    alert("網路由 " + type + " 變化為 " + connection.type);
}
//監聽網路型別發生變化
connection.addEventListener('typechange', updateConnectionStatus);

有了這些,我們就可以根據不同的網路環境去載入不同的資源去最大程度上豐富使用者體驗。

我們上面所提及到的,很多都是和網路(網際網路)相關,但是有的時候,我們想在沒有網路的環境下,也想傳送一些資料該怎麼辦。這種情況可能在不久的將來,在我們的網頁裡面也能實現了,這個就是接下來的NFC(為什麼我會想到KFC)

NFC

簡介:

近場通訊/近距離無線通訊技術。

其實說實在的,這個功能我並沒有在我的頁面裡面調試出來。主要的一個原因是~這貨目前只是在firefox os系統裡面的firefox瀏覽器裡面實現了,手頭上沒這裝置。不過從他們官網的例子中,我大概地可以感受得到這貨的好用,有興趣的同學自行前往學習:https://developer.mozilla.org/en-US/docs/Web/API/NFC_API/Using_the_NFC_API

當然了,如果你手頭上剛好有兩部帶有NFC晶片的三星手機,可以試試。解鎖螢幕,將兩部三星手機後殼貼近,聽見&ldquo;滴&rdquo;的一聲後,注意看螢幕上的變化。然後點選螢幕,再去看看另外一個手機上發生了什麼。

清脆&ldquo;滴&rdquo;的一聲,多好的使用者行為反饋,忍不住還多嘗試了幾次,忽然就感覺這種靠聲音的提醒,似乎忽略了一些失聰的人群。如果加上點震動的話~似乎就完美了。不是於是乎,咱們本片的最後一個話題引出。

vibrate

簡介:

裝置震動

核心程式碼:

navigator.vibrate = navigator.vibrate ||  navigator.webkitVibrate || 
                                navigator.mozVibrate || navigator.msVibrate;
navigator.vibrate(value);
navigator.vibrate(0);

vibrate的引數為震動的時間,

如果值為0,說明停止震動

值為一個數組的話,奇數項表示的是震動時間,偶數項表示的為間隔時間。

比如:vibrate(1000,1000,2000)  就是表示震動1秒之後暫停1秒,再震動2秒

有興趣的,掃下這個二維碼可體驗

1435222467_54_w175_h174111111111.png

一口氣說了這麼一堆,其實後面的這幾個點,都還在標準化的路上,不同機型/平臺支援不太一致,在實際專案中使用還是要注意點區別對待的~你們先回味著,我一個人先傷一會兒心去。

參考文獻:
https://developer.mozilla.org/en-US/docs/Web/API
http://webaudiodemos.appspot.com/
http://www.w3.org/2009/dap/

【走在時代前列的騰訊HTML 5精品好文】