走向或远离移动中的模型

Go towards or away from the model in mobile

,我得到一个 WebVR 页面,它在桌面上运行良好,但在移动设备上运行良好 phone 我无法靠近模型(看起来更像天空盒) .

除了环顾四周,还希望能够走向/远离模型(分别用两根手指远离或靠近)。

经过一番搜索,找到了 an example 我要查找的此功能的使用位置。

我怎样才能让相同的移动功能适用于我的案例?

1) 轨道控制

如果您希望您的体验围绕模型旋转、围绕模型移动相机并放大和缩小 - 我会说 orbit controls 正是您要找的东西:

<a-entity camera look-controls 
          orbit-controls="target: 0 1.6 -0.5; initialPosition: 0 5 15"></a-entity>

摄像机将围绕定义的 target 移动。适用于移动触摸事件。 用 gltf 个模型 here.

检查一下

2) 捏合移动相机

如果您想将相机移向或移开它所注视的方向,据我所知,您必须在自定义组件中实现此类行为。穷人版本可能看起来有点像这样:

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>

看看here


如果您想将相机移向模型(而不是它所面对的方向),您只需将提取相机方向(在 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/aframe-orbit-controls@1.2.0/dist/aframe-orbit-controls.min.js"></script>
    <script src="https://unpkg.com/aframe-supercraft-loader@1.1.3/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>

这就是最终结果