来自 在我之前的回答上加码我得到了一个WebVR页面,在桌面上可以正常工作,但在手机上,我无法走近模型(看起来更像一个天空盒)。
希望能够走向远离模型(用两根手指分别去,远离对方或更近),除了环顾四周。
经过一番搜索,发现 例子 的,我寻找的这个功能在哪里使用。
如何才能让我的案例也能使用同样的手机功能?
如果你想让你的体验围绕着一个模型,在它周围移动相机,并放大和缩小--我会说是 轨道控制 就是你要找的东西。
<a-entity camera look-controls
orbit-controls="target: 0 1.6 -0.5; initialPosition: 0 5 15"></a-entity>
摄像机将围绕定义的 target
. 与移动触摸事件一起工作.检查它与 gltf
模型 此处.
如果你想把摄像机向远处或近处移动,据我所知,你必须在一个自定义组件中实现这种行为。一个穷人的版本可能看起来有点像这样。
AFRAME.registerComponent('pinch-controls', {
init: function() {
// moveCamera uses variables from 'this' scope
this.moveCamera.bind(this);
// we'll use this to get the 'pinch direction'
this.distance = 0;
// we'll keep here the camera's current direction
this.direction = new THREE.Vector3();
// camera entity reference
this.camera = document.querySelector("[camera]");
// listeners
document.body.addEventListener('touchstart', event => {
// we're interested only in two - finger pinches
if (event.touches.length != 2) return 0;
// calculate the distance
this.distance = this.calculatePinchDistance(event);
// we don't want the touch to rotate the camera around
this.el.setAttribute('look-controls', 'touchEnabled', false);
}, false);
document.body.addEventListener('touchend', event => {
// when the pinch ends - restore the look-controls
if (event.touches.length != 1) this.el.setAttribute('look-controls', 'touchEnabled', true);
}, false);
document.body.addEventListener('touchmove', event => {
// we're interested only in two - finger pinches
if (event.touches.length != 2) return 0;
// compare the distances to determine which direction should we move
var distance = this.calculatePinchDistance(event);
let speed = (distance < this.distance) ? -0.2 : 0.2;
this.moveCamera(speed);
// keep the distance for the next callback
this.distance = distance;
}, false);
},
calculatePinchDistance(event) {
var dx = event.touches[0].pageX - event.touches[1].pageX;
var dy = event.touches[0].pageY - event.touches[1].pageY;
return Math.sqrt(dx * dx + dy * dy);
},
moveCamera: function(speed) {
// get the camera direction, and multiply it by the desired 'speed'
this.el.sceneEl.camera.getWorldDirection(this.direction);
this.direction.multiplyScalar(speed);
// apply the change to the actual position
var pos = this.el.getAttribute("position");
pos.add(this.direction);
this.el.setAttribute("position", pos);
}
}
// HTML
// <a-entity camera look-controls pinch-controls></a-entity>
看看吧 此处
如果你想把摄像机朝向模型移动(而不是朝向它所面对的方向),你只需把提取摄像机方向(在 moveCamera
)与计算摄像机<->模型方向。
// instead of
// this.el.sceneEl.camera.getWorldDirection(this.direction);
// grab the direction towards the model
this.direction.copy(this.el.object3D.position)
this.direction.add(modelReference.object3D.position)
this.direction.normalize();
// (...)
最后使用的代码是
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Octant Cube - by Dodds, H. & Peres, T.</title>
<meta name="description" content="Present in the Taxonomy article">
<script src="https://kit.fontawesome.com/c9500776a0.js" crossorigin="anonymous"></script>
<script src="misc/codeBtn.js"></script>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/aframe-orbit-controls.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/aframe-supercraft-loader.js"></script>
<style>
#toggleBtn {
position: fixed;
z-index: 9999;
margin: 25px;
font-size: 3em;
color: rgb(128, 0, 128);
cursor: pointer;
}
#toggleBtn:hover {
color: rgba(128, 0, 128, 0.6);
}
</style>
<script>
// Models swap component
AFRAME.registerComponent('content-manager', {
init: function() {
const btn = document.querySelector("#toggleBtn")
const castle = document.querySelector("#castle")
const fish = document.querySelector("#fish")
btn.addEventListener("click", e => {
if (castle.getAttribute("visible")) {
castle.emit("fadeOut")
btn.classList.remove("fa-fish")
btn.classList.add("fa-landmark")
} else {
fish.emit("fadeOut")
btn.classList.remove("fa-landmark")
btn.classList.add("fa-fish")
}
})
fish.addEventListener('animationcomplete__fadeout', e => {
fish.setAttribute("visible", "false")
castle.setAttribute("visible", "true")
castle.emit("fadeIn")
})
castle.addEventListener('animationcomplete__fadeout', e => {
castle.setAttribute("visible", "false")
fish.setAttribute("visible", "true")
fish.emit("fadeIn")
})
}
})
// move the camera on pinching
AFRAME.registerComponent('pinch-controls', {
init: function() {
// bind the methods that use the scope variables
this.moveCamera.bind(this);
// use this to keep track whether the user is moving forward or backwards
this.distance = 0;
// store the camera direction here
this.direction = new THREE.Vector3();
// camera entity reference
this.camera = document.querySelector("[camera]");
document.body.addEventListener('touchstart', event => {
// react only on two finger pinches
if (event.touches.length != 2) return 0;
this.distance = this.calculatePinchDistance(event);
// prevent the look controls to rotate the camera while pinching
this.el.setAttribute('look-controls', 'touchEnabled', false);
}, false);
document.body.addEventListener('touchend', event => {
// restore the look-controls
if (event.touches.length != 1) this.el.setAttribute('look-controls', 'touchEnabled', true)
}, false);
document.body.addEventListener('wheel', e => {
this.moveCamera(e.deltaY < 0 ? -0.2 : 0.2);
})
document.body.addEventListener('touchmove', event => {
// we're interested only in pinching
if (event.touches.length != 2) return 0;
// calculate the pinch difference and move the camera
var distance = this.calculatePinchDistance(event);
let multiplier = (distance < this.distance) ? -0.2 : 0.2;;
if (!isNaN(multiplier)) this.moveCamera(multiplier);
// for later use
this.distance = distance;
}, false);
},
calculatePinchDistance: function(mouseEvent) {
var dx = event.touches[0].pageX - event.touches[1].pageX;
var dy = event.touches[0].pageY - event.touches[1].pageY;
return Math.sqrt(dx * dx + dy * dy);
},
moveCamera: function(speed) {
this.el.sceneEl.camera.getWorldDirection(this.direction);
this.direction.multiplyScalar(speed);
var pos = this.el.getAttribute("position");
pos.add(this.direction);
this.el.setAttribute("position", pos)
}
})
</script>
</head>
<body>
<a-scene background="color: #FAFAFA">
<a-assets>
<a-asset-item id="octant" src="octant.glb"></a-asset-item>
</a-assets>
<a-entity position="0 0.347 -4" rotation="0 60 -1" gltf-model="#octant" scale="5 5 5" animation__fadeIn="property: scale; dur: 150; from: 0.001 0.001 0.001; to: 0.5 0.5 0.5; easing: easeInQuad; startEvents: fadeIn" animation__fadeOut="property: scale; dur: 150; from: 0.5 0.5 0.5; to: 0.001 0.001 0.001; easing: easeInQuad; startEvents: fadeOut"></a-entity>
<a-entity camera look-controls
orbit-controls="target: 0 1.6 -0.5; initialPosition: 0 5 15"></a-entity>
</a-scene>
</body>
</html>
这就是最后的结果