如何使用 JavaScript 为一帧中的相机运动设置动画?

How do I animate a camera movement in a-frame, using JavaScript?

我正在使用 A-Frame 在桌面的常规网页上构建虚拟游览,运行。没有VR导航,只是移动和点击鼠标光标。

我会在a-scene上面有几个按钮。每个按钮都会将相机指向不同的方向。我设法让它工作。下一步是将它设置为动画,就好像相机正在平移到它的新方向,而不是直接跳到它。

有没有办法实现这一点,同时设置动画的持续时间和缓动?

我从 this SO post 知道如何在框架内做到这一点。但是因为我在它之外调用一个函数,所以我对如何让它工作有点迷茫。

这是我的代码:

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>

有几种方法可以做到这一点。一种是直接在 look-controls 组件的 tick 函数中管理它。这意味着您需要根据外观控件创建自己的组件。它需要一些技巧,但它确实有效。 更简单的方法是使用 requestAnimationFrame 来管理移动。这是我根据您的代码制作的一个完整的示例。您可以将持续时间更改为您喜欢的时间。

<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>