旋转 webGL canvas 以在纵向移动设备上显示为横向 phone
Rotate webGL canvas to appear landscape-oriented on a portrait-oriented mobile phone
我正在使用 a-frame 并尝试完成此任务 - 当移动设备处于纵向时(即设备宽度 = 414px 和设备高度 = 736px).
我已通过以下步骤成功完成此操作
camera.aspect = 736 / 414;
camera.updateProjectionMatrix();
renderer.setSize(736, 414);
在css...
.a-canvas {
transform: rotate(90deg) translate(161px, 161px);
height: 414px !important;
width: 736px !important;
}
这一切都很好,除了一件大事……我的场景中有 3D 按钮,当我点击它们时,它们不会与旋转的 canvas 对齐,而是它们的可点击位置保持在与旋转 canvas 之前相同的位置。
我尝试在场景的 object3D 上设置 matrixWorldNeedsUpdate = true 以及 updateWorldMatrix() 但没有成功。我尝试在 raycaster 上调用 refreshObjects 但没有成功。我尝试旋转场景和相机,但没有成功。
我不知道还能做什么。任何帮助将不胜感激!
答案:
感谢 Marquizzo 和 gman 的帮助。这是更新的 a-frame 源代码 (v1.0.4),使 raycaster 能够正确处理这种强制景观 canvas
// line: 66884
onMouseMove: (function () {
var direction = new THREE.Vector3();
var mouse = new THREE.Vector2();
var origin = new THREE.Vector3();
var rayCasterConfig = {origin: origin, direction: direction};
return function (evt) {
var bounds = this.canvasBounds;
var camera = this.el.sceneEl.camera;
var left;
var point;
var top;
camera.parent.updateMatrixWorld();
// Calculate mouse position based on the canvas element
if (evt.type === 'touchmove' || evt.type === 'touchstart') {
// Track the first touch for simplicity.
point = evt.touches.item(0);
} else {
point = evt;
}
left = point.clientX - bounds.left;
top = point.clientY - bounds.top;
// mouse.x = (left / bounds.width) * 2 - 1;
// mouse.y = -(top / bounds.height) * 2 + 1;
// HAYDEN's CODE: flipping x and y coordinates to force landscape
// --------------------------------------------------------------
let clickX = (left / bounds.width) * 2 - 1;
let clickY = - (top / bounds.height) * 2 + 1;
mouse.x = -clickY;
mouse.y = clickX;
// --------------------------------------------------------------
origin.setFromMatrixPosition(camera.matrixWorld);
direction.set(mouse.x, mouse.y, 0.5).unproject(camera).sub(origin).normalize();
this.el.setAttribute('raycaster', rayCasterConfig);
if (evt.type === 'touchmove') { evt.preventDefault(); }
};
})(),
A-Frame 在内部使用 Raycaster
来确定您单击的位置是否击中了对象。您可以在该概念的 Three.js 文档 the raycaster needs the mouse x&y coordinates to determine where you clicked. Here's a working demo 中看到。但是,根据您的设置,x, y
会变成 -y, x
。
我认为您必须编写自己的 Raycaster 函数来触发 click
事件,而不是依赖内置的 AFrame 功能,然后交换 x&y 值:
function onClick() {
let clickX = ( event.clientX / window.innerWidth ) * 2 - 1;
let clickY = - ( event.clientY / window.innerHeight ) * 2 + 1;
mouse.x = -clickY;
mouse.y = clickX;
// Then continue with raycaster.setFromCamera(), etc...
}
window.addEventListener( 'click', onClick, false );
我正在使用 a-frame 并尝试完成此任务 - 当移动设备处于纵向时(即设备宽度 = 414px 和设备高度 = 736px).
我已通过以下步骤成功完成此操作
camera.aspect = 736 / 414;
camera.updateProjectionMatrix();
renderer.setSize(736, 414);
在css...
.a-canvas {
transform: rotate(90deg) translate(161px, 161px);
height: 414px !important;
width: 736px !important;
}
这一切都很好,除了一件大事……我的场景中有 3D 按钮,当我点击它们时,它们不会与旋转的 canvas 对齐,而是它们的可点击位置保持在与旋转 canvas 之前相同的位置。
我尝试在场景的 object3D 上设置 matrixWorldNeedsUpdate = true 以及 updateWorldMatrix() 但没有成功。我尝试在 raycaster 上调用 refreshObjects 但没有成功。我尝试旋转场景和相机,但没有成功。
我不知道还能做什么。任何帮助将不胜感激!
答案:
感谢 Marquizzo 和 gman 的帮助。这是更新的 a-frame 源代码 (v1.0.4),使 raycaster 能够正确处理这种强制景观 canvas
// line: 66884
onMouseMove: (function () {
var direction = new THREE.Vector3();
var mouse = new THREE.Vector2();
var origin = new THREE.Vector3();
var rayCasterConfig = {origin: origin, direction: direction};
return function (evt) {
var bounds = this.canvasBounds;
var camera = this.el.sceneEl.camera;
var left;
var point;
var top;
camera.parent.updateMatrixWorld();
// Calculate mouse position based on the canvas element
if (evt.type === 'touchmove' || evt.type === 'touchstart') {
// Track the first touch for simplicity.
point = evt.touches.item(0);
} else {
point = evt;
}
left = point.clientX - bounds.left;
top = point.clientY - bounds.top;
// mouse.x = (left / bounds.width) * 2 - 1;
// mouse.y = -(top / bounds.height) * 2 + 1;
// HAYDEN's CODE: flipping x and y coordinates to force landscape
// --------------------------------------------------------------
let clickX = (left / bounds.width) * 2 - 1;
let clickY = - (top / bounds.height) * 2 + 1;
mouse.x = -clickY;
mouse.y = clickX;
// --------------------------------------------------------------
origin.setFromMatrixPosition(camera.matrixWorld);
direction.set(mouse.x, mouse.y, 0.5).unproject(camera).sub(origin).normalize();
this.el.setAttribute('raycaster', rayCasterConfig);
if (evt.type === 'touchmove') { evt.preventDefault(); }
};
})(),
A-Frame 在内部使用 Raycaster
来确定您单击的位置是否击中了对象。您可以在该概念的 Three.js 文档 the raycaster needs the mouse x&y coordinates to determine where you clicked. Here's a working demo 中看到。但是,根据您的设置,x, y
会变成 -y, x
。
我认为您必须编写自己的 Raycaster 函数来触发 click
事件,而不是依赖内置的 AFrame 功能,然后交换 x&y 值:
function onClick() {
let clickX = ( event.clientX / window.innerWidth ) * 2 - 1;
let clickY = - ( event.clientY / window.innerHeight ) * 2 + 1;
mouse.x = -clickY;
mouse.y = clickX;
// Then continue with raycaster.setFromCamera(), etc...
}
window.addEventListener( 'click', onClick, false );