ThreeJS TrackballControls平移/旋转在Vue中不起作用

时间:2019-04-13 13:37:02

标签: javascript vue.js three.js nuxt.js

我尝试搜索此内容,但很快就空了。我在学习ThreeJS(使用r102)很有趣,但在获取TrackballControl平移和旋转功能以使其正常工作时遇到问题。缩放控件工作得很好。

我没有使用three节点模块,因为移出核心的有用的帮助程序类不是模块,并且由于全局名称空间污染而无法在Vue中工作(我的情况是Nuxt)。我已经开始使用three-full节点模块进行ThreeJS学习,因为它包含对移出核心库的那些示例的重写。

我已经在three-fullthree-trackballcontrols节点模块中尝试过TrackballControls,并且在其中任何一个中都无法进行平移和旋转。我没有任何错误,尝试平移和旋转时什么也没有发生。

这是我的单个vue文件,我在其中手动创建了一些几何图形,并通过RAF循环“动画化”了它们的位置。

<template>
  <section class="section">
    <div class="hero is-fullheight">
      <div 
        id="three-element" 
        ref="threeElement" 
        @click="addManualGeometry"/>
      <button @click="startScene">Start</button>
    </div>
  </section>
</template>

<script>
import * as THREE from "three-full";

export default {
  components: {},
  data() {
    return {
      scene: undefined,
      camera: undefined,
      renderer: undefined,
      stats: undefined,
      plane: undefined,
      planeDimensions: [60, 40],
      objectCount: 0,
      started: false,
      step: 0,
      trackballControls: undefined,
      clock: undefined
    };
  },
  mounted() {
    console.log(THREE);
    this.setup();
    //this.addPlane();
    this.addLight();
    this.addManualGeometry();
    this.positionCamera();
    this.setupClock();
    this.setupTrackballControls();
    this.$refs.threeElement.appendChild(this.renderer.domElement);
  },
  methods: {
    setup() {
      // set up scene, camera, renderer, and axes
      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      this.renderer = new THREE.WebGLRenderer();
      this.renderer.setClearColor(new THREE.Color(0x000000));
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMapSoft = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;

      window.addEventListener("resize", this.handleWindowResize);
    },
    handleWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    addPlane() {
      // create plane geometry and material
      const planeGeometry = new THREE.PlaneGeometry(
        this.planeDimensions[0],
        this.planeDimensions[1],
        1,
        1
      );
      const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xaaaaaa });
      this.plane = new THREE.Mesh(planeGeometry, planeMaterial);
      this.plane.rotation.x = -0.5 * Math.PI;
      this.plane.position.set(15, 0, 0);
      this.plane.receiveShadow = true;

      // add plane to the scene
      this.scene.add(this.plane);
    },
    addManualGeometry() {
      const vertices = [
        new THREE.Vector3(1, 3, 1),
        new THREE.Vector3(1, 3, -1),
        new THREE.Vector3(1, -1, 1),
        new THREE.Vector3(1, -1, -1),
        new THREE.Vector3(-1, 3, -1),
        new THREE.Vector3(Math.random(), Math.random(), 1),
        new THREE.Vector3(-1, Math.random(), -1),
        new THREE.Vector3(-1, -1, 1)
      ];
      const faces = [
        new THREE.Face3(0, 2, 1),
        new THREE.Face3(2, 3, 1),
        new THREE.Face3(4, 6, 5),
        new THREE.Face3(6, 7, 5),
        new THREE.Face3(4, 5, 1),
        new THREE.Face3(5, 0, 1),
        new THREE.Face3(7, 6, 2),
        new THREE.Face3(6, 3, 2),
        new THREE.Face3(5, 7, 0),
        new THREE.Face3(7, 2, 0),
        new THREE.Face3(1, 3, 4),
        new THREE.Face3(3, 6, 4)
      ];
      const geom = new THREE.Geometry();

      geom.vertices = vertices;
      geom.faces = faces;
      // this makes threejs determine a normal vector for each of the faces
      geom.computeFaceNormals();

      const materials = [
        new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true }),
        new THREE.MeshLambertMaterial({
          opacity: 0.9,
          color: Math.random() * 0x44ff44,
          transparent: true
        })
      ];

      const mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
      mesh.castShadow = true;
      mesh.children.forEach(child => {
        child.castShadow = true;
      });
      this.scene.add(mesh);
    },
    updateGeometryRotation(shape, coords) {
      shape.rotation.x += coords[0];
      shape.rotation.y += coords[1];
      shape.rotation.z += coords[2];
    },
    addLight() {
      // add spotlight and ambient light
      const spotLight = new THREE.SpotLight(0xffffff);
      spotLight.position.set(-40, 60, -10);
      spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024);
      spotLight.shadow.camera.far = 130;
      spotLight.shadow.camera.near = 40;
      spotLight.castShadow = true;
      spotLight.decay = 2;
      spotLight.penumbra = 0.05;
      this.scene.add(spotLight);

      const ambientLight = new THREE.AmbientLight(0x3c3c3c);
      this.scene.add(ambientLight);
    },
    positionCamera() {
      // position the camera for the scene
      this.camera.position.set(-30, 40, 30);
      this.camera.lookAt(this.scene.position);
    },
    setupClock() {
      this.clock = new THREE.Clock();
    },
    setupTrackballControls() {
      this.trackballControls = new THREE.TrackballControls(
        this.camera,
        this.renderer.domElement
      );
    },
    renderScene() {
      const rotationArray = [0.02, 0.02, 0.02];

      this.trackballControls.update(this.clock.getDelta());

      this.scene.traverse(obj => {
        if (obj instanceof THREE.Mesh && obj !== this.plane) {
          obj.rotation.x *= Math.random() * 0.002;
          obj.rotation.y *= Math.random() * 0.002;
          obj.translateX(Math.random() * 0.04);
          obj.rotation.z += Math.random() * 0.04;
        }
      });

      window.RAF = requestAnimationFrame(this.renderScene);
      this.renderer.render(this.scene, this.camera);
    },
    startScene() {
      if (this.started) return;

      this.renderScene();

      this.started = !this.started;
    }
  }
};
</script>

<style scoped>
button {
  position: absolute;
  top: 10px;
  left: 0;
  right: 0;
  margin: auto;
  display: block;
  width: 80px;
  background: red;
  color: white;
  border-color: transparent;
  border-radius: 10px;
  outline: unset;
}
</style>
来自three-full

Here's the TrackballControls source code。我尚不清楚为什么缩放会起作用但不能平移或旋转,并且由于我是ThreeJS菜鸟,因此在TrackballControls源代码中进行挖掘目前有点麻烦。如果有兴趣,请here is the github repo I'm making these demos in。有问题的文件位于pages/learn-threejs-book/manual-geometry.vue中。

有人对此有任何建议吗?您之前有在Vue或React中使用TrackballControls吗?我觉得只是我的问题,但我不确定是什么。

更新:

我能够扔掉我在一个旧的github问题中发现的一些代码来像这样手动旋转相机:

changeCameraPosition(e) {
      e.preventDefault();
      e.stopPropagation();
      const theta = 0.1; //the speed of rotation

      console.log(e);

      if (e.key === "a") {
        const x = this.camera.position.x;
        const z = this.camera.position.z;

        console.log(this.camera);

        this.camera.position.x = x * Math.cos(theta) + z * Math.sin(theta);
        this.camera.position.z = z * Math.cos(theta) - x * Math.sin(theta);
        this.camera.lookAt(this.scene.position);
      }
    },

我真的很想使用ThreeJS随附的TrackballControls,但这暂时适用于我的情况。

0 个答案:

没有答案