开发时发现同根iframe子页面可以直接检测到deviceorientation事件,但跨域iframe不可以,因此通过postMessage传递信息。
https://github.com/w3c/deviceorientation/issues/57
将来w3c直接支持子页面deviceorientation事件就更好了。
父页面:
<!DOCTYPE html>
<html>
<head>
<title>blank</title>
<script type="text/javascript">
var onDeviceOrientationChangeEvent = function(event) {
window.deviceOrientation = event;
};
window.addEventListener('message', function(rs) {
if (rs.data === 'gyroscope') {
window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
var nInterval = window.setInterval(function() {
var val = {
"act": "gyroscope",
"val": {
alpha: window.deviceOrientation.alpha,
beta: window.deviceOrientation.beta,
gamma: window.deviceOrientation.gamma
}
};
//获取iframe的id
var ifr = document.getElementById('mainFrame');
//iframe的路径
var url = 'http://172.19.36.50:8083/panorama12/index.html';
ifr.contentWindow.postMessage(JSON.stringify(val), url);
}, 67);
}
});
</script>
</head>
<body>
<iframe id="mainFrame" src="http://172.19.36.50:8083/panorama12/index.html" style="width: 1024px;height:768px;"></iframe>
</body>
</html>
子页面通知父级监听deviceorientation事件处(非必要代码):
if(top !== self) {
window.parent.postMessage("gyroscope", '*');
}
子页面接受信息处:
window.onmessage = function(event) {
var data = eval('(' + event.data + ')');
if (data.act === 'gyroscope') {
window.deviceOrientation = data.val;
}
}
three.js里的DeviceOrientationControls.js修改处:
/**
* @author richt / http://richt.me
* @author WestLangley / http://github.com/WestLangley
*
* W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
*/
THREE.DeviceOrientationControls = function (object) {
var scope = this;
this.object = object;
this.object.rotation.reorder("YXZ");
this.enabled = true;
this.deviceOrientation = {};
this.screenOrientation = 0;
this.alpha = 0;
this.alphaOffsetAngle = 0;
var onDeviceOrientationChangeEvent = function (event) {
scope.deviceOrientation = event;
};
var onScreenOrientationChangeEvent = function () {
scope.screenOrientation = window.orientation || 0;
};
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
var setObjectQuaternion = function () {
var zee = new THREE.Vector3(0, 0, 1);
var euler = new THREE.Euler();
var q0 = new THREE.Quaternion();
var q1 = new THREE.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); // - PI/2 around the x-axis
return function (quaternion, alpha, beta, gamma, orient) {
euler.set(beta, alpha, -gamma, 'YXZ'); // 'ZXY' for the device, but 'YXZ' for us
quaternion.setFromEuler(euler); // orient the device
quaternion.multiply(q1); // camera looks out the back of the device, not the top
quaternion.multiply(q0.setFromAxisAngle(zee, -orient)); // adjust for screen orientation
}
} ();
this.connect = function () {
onScreenOrientationChangeEvent(); // run once on load
if (top === self) {
window.addEventListener('orientationchange', onScreenOrientationChangeEvent, false);
window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
}
else {
}
scope.enabled = true;
};
this.disconnect = function () {
window.removeEventListener('orientationchange', onScreenOrientationChangeEvent, false);
window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
scope.enabled = false;
};
this.update = function () {
if (scope.enabled === false) return;
if (top !== self) {
scope.deviceOrientation = window.deviceOrientation;
}
else {
}
var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad(scope.deviceOrientation.alpha) + this.alphaOffsetAngle : 0; // Z
var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad(scope.deviceOrientation.beta) : 0; // X'
var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad(scope.deviceOrientation.gamma) : 0; // Y''
var orient = scope.screenOrientation ? THREE.Math.degToRad(scope.screenOrientation) : 0; // O
setObjectQuaternion(scope.object.quaternion, alpha, beta, gamma, orient);
this.alpha = alpha;
};
this.updateAlphaOffsetAngle = function (angle) {
this.alphaOffsetAngle = angle;
this.update();
};
this.dispose = function () {
this.disconnect();
};
this.connect();
};