H5指北針(基於deviceorientation)

H5裏有個deviceorientation API,能夠檢測移動設備的旋轉狀態,進而能夠實現指南針的功能,只不過是以北方爲基準的。html

該API提供提供了三項數據,alpha(設備Z軸旋轉角度),beta(X軸),gamma(Y軸),通常alpha就是與正北方的角度差。然而不一樣設備、不一樣瀏覽器對此的理解是很不同的。。。ios

  • ios下直接使用webkitCompassHeading便可
  • 能夠經過實現w3c的標準算法自行計算角度,這個值應該等同於webkitCompassHeading
  • Android browser使用alpha通常ok
  • chrome使用alpha,須要減去270(deg)
  • 火狐呢,要減去180

代碼以下:web

// 指南針
var compass = document.getElementById('compass');
// compass heading取值模式
var mode = '0';
// 最近一次動畫的時間
var now = Date.now();

if (window.DeviceOrientationEvent) {
	document.getElementById('options').addEventListener('click', function(e){
		if (e.target.tagName === 'INPUT') {
			mode = e.target.value;
		}
	}, false);
	window.addEventListener('deviceorientation', function(event) {
		var ntime = Date.now();
		if (ntime - now < 100) return; // 避免過於頻繁的動畫
		now = ntime;
		var heading;
		// iOS設備直接使用webkitCompassHeading
		if ('webkitCompassHeading' in event) {
		  // 因爲實際是指北的,須要反轉角度,下同
			heading = 360 - event.webkitCompassHeading;
		} else if (window.chrome) {
			// chrome瀏覽器的event.alpha是錯誤的,計算出來的值也是錯的,須要修正
			heading = event.alpha - 270;
			if (heading < 0) heading += 360;
		} else {
			if (mode === '0') {
			  // 安卓瀏覽器的event.alpha直接可用,這樣反應快點
			  heading = event.alpha;
			} else {
			  // 按照w3c標準規則計算compass heading
				heading = 360 - compassHeading(event.alpha, event.beta, event.gamma);
			}
			// TODO: 火狐始終減去180
			// heading -= 180;
		}

		compass.style.Transform = 'rotate(' + heading + 'deg)';
		compass.style.WebkitTransform = 'rotate(' + heading + 'deg)';
		compass.style.MozTransform = 'rotate(' + heading + 'deg)';

		var info = 'webkitHeading:' + event.webkitCompassHeading + '<br>' +
			'heading: ' + heading + '<br>' +
			'alpha: ' + event.alpha + '<br>' +
			'beta:' + event.beta + '<br>' +
			'gamma:' + event.gamma + '<br>' +
			'chrome:' + !!window.chrome + '<br>';
		document.getElementById('info').innerHTML = info;
	}, false);
} else {
	document.getElementById('info').innerHTML = '你的瀏覽器不支持陀螺儀!';
}

// http://stackoverflow.com/questions/18112729/calculate-compass-heading-from-deviceorientation-event-api/21829819#21829819
function compassHeading(alpha, beta, gamma) {
	// Convert degrees to radians
	var alphaRad = alpha * (Math.PI / 180);
	var betaRad = beta * (Math.PI / 180);
	var gammaRad = gamma * (Math.PI / 180);

	// Calculate equation components
	var cA = Math.cos(alphaRad);
	var sA = Math.sin(alphaRad);
	var cB = Math.cos(betaRad);
	var sB = Math.sin(betaRad);
	var cG = Math.cos(gammaRad);
	var sG = Math.sin(gammaRad);

	// Calculate A, B, C rotation components
	var rA = - cA * sG - sA * sB * cG;
	var rB = - sA * sG + cA * sB * cG;
	var rC = - cB * cG;

	// Calculate compass heading
	var compassHeading = Math.atan(rA / rB);

	// Convert from half unit circle to whole unit circle
	if(rB < 0) {
		compassHeading += Math.PI;
	}else if(rA < 0) {
		compassHeading += 2 * Math.PI;
	}

	// Convert radians to degrees
	compassHeading *= 180 / Math.PI;

	return compassHeading;
}

在線演示地址: http://sandbox.runjs.cn/show/mysqbqeq算法

須要注意的是,H5的陀螺儀精度和app的比起來,比較低,須要屢次調教後才大體可靠。固然,這和算法也有很大關係。chrome

相關文章
相關標籤/搜索