I am working with A-Frame to build a virtual tour, running on a regular webpage, in the desktop. No VR navigation, just moving and clicking the mouse cursor around.
I will have several buttons above the a-scene. Each button will point the camera at a different direction. I managed to get that working. Next step would be animating it as if the camera is panning to its new direction, instead of jumping right to it.
Is there a way to achieve this, having the possibility to also set the duration and easing of the animation?
I know, from this SO post how to do that inside a-frame. But since I am calling a function outside of it, I am a bit lost on how to get this working.
This is my code:
function moveCamera() {
var el = document.querySelector("a-camera");
el.components["look-controls"].pitchObject.rotation.x = -0.1;
el.components["look-controls"].yawObject.rotation.y = 0.85;
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="moveCamera()">Move Camera</button>
<div class="sceneWrapper">
<a-scene embedded background="color: #FAFAFA">
<a-entity id='cameraWrapper' position="0 0 0">
<a-camera wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
<a-animation attribute="position"
dur="2000"
easing="linear"
to="0 1.6 -10"></a-animation>
</a-camera>
</a-entity>
<a-sky color="#c7dcff"></a-sky>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
</a-scene>
</div>
There are several ways to do this. One would be to manage it directly in the tick function of the look-controls component. It means you would need to create your own component based on look-controls. It needs a few tricks but it works. A more simple way is to use requestAnimationFrame to manage the movement. Here is a fully working example I made based on your code. You can change the duration to what pleases you.
<html>
<head>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
</head>
<body>
<a-scene background="color: #FAFAFA">
<a-entity id='cameraWrapper' position="0 0 0">
<a-camera wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
<a-animation attribute="position" dur="2000" easing="linear" to="0 1.6 -10"></a-animation>
</a-camera>
</a-entity>
<a-sky color="#c7dcff"></a-sky>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
</a-scene>
<button type="button" style="position: fixed; top: 10px; left: 10px;" onclick="moveCamera(-0.1, 0.85)">Move Camera</button>
<script type="text/javascript">
var start, x_start, y_start, x_rotation, y_rotation;
var duration = 1000;
var camera = document.querySelector("a-camera");
function moveCamera(x_destination, y_destination) {
start = null;
x_start = camera.components["look-controls"].pitchObject.rotation.x;
x_rotation = x_destination - x_start;
y_start = camera.components["look-controls"].yawObject.rotation.y;
y_rotation = y_destination - y_start;
requestAnimationFrame(step);
}
function step(timestamp) {
if (start === null) start = timestamp;
var progress = timestamp - start;
camera.components["look-controls"].pitchObject.rotation.x = x_start + x_rotation * progress / duration;
camera.components["look-controls"].yawObject.rotation.y = y_start + y_rotation * progress / duration;
if (progress < duration) {
requestAnimationFrame(step);
}
}
</script>
</body>
</html>