H5 compass (based on deviceorientation)

There is a deviceorientation API in H5, which can detect the rotation state of the mobile device, and then realize the function of the compass, but it is based on the north.

The API provides three items of data, alpha (device Z-axis rotation angle), beta (X-axis), gamma (Y-axis). Generally, alpha is the angle difference from true north. However, different devices and different browsers understand this very differently. . .

  • webkitCompassHeadingYou can use it directly under ios
  • You can calculate the angle yourself by implementing the standard algorithm of w3c, this value should be equivalent towebkitCompassHeading
  • Android browser alphais generally ok
  • Chrome use alpha, need to subtract 270 (deg)
  • What about Firefox, minus 180

code show as below:

// 指南针
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;
}

Online demo address: http://sandbox.runjs.cn/show/mysqbqeq

It should be noted that the accuracy of the gyroscope of the H5 is lower than that of the app, and it needs to be adjusted several times before it is generally reliable. Of course, this also has a lot to do with the algorithm.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325776523&siteId=291194637