vue+threejs写应用:禁止水平垂直旋转、平移、缩放

1,779 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情


写在前面

本文用vue+threejs写应用:禁止水平垂直旋转、平移、缩放

代码说明

当我们在代码中使用了threejs的轨道控制器OrbitControls模块,我们就可以通过【拖动+鼠标左键】控制界面的水平垂直旋转,通过【拖动+鼠标右键】控制界面的平移,通过【滚动+鼠标中键】控制界面的缩放。

但是在实际应用中,我们可能会想禁止这些操作中的某些或所有。OrbitControls模块也提供了一些方法来帮助我们实现禁止这些操作的功能。

禁止所有操作

enabled属性:当设置为false时即可禁止所有的鼠标操作响应。

在代码中创建了【禁用/开启轨道控制器】的按钮,点击按钮执行this.controls.enabled = !this.controls.enabled;即可切换禁用/开启轨道控制器。

禁止水平垂直旋转

enableRotate属性:当设置为false时即可禁止水平垂直旋转。

在代码中创建了【禁用/开启水平/垂直旋转】的按钮,点击按钮执行this.controls.enableRotate = !this.controls.enableRotate;即可切换禁用/开启水平垂直旋转。

禁止平移

enablePan属性:当设置为false时即可禁止平移。

在代码中创建了【禁用/开启平移】的按钮,点击按钮执行this.controls.enablePan = !this.controls.enablePan;即可切换禁用/开启平移。

禁止缩放

enableZoom属性:当设置为false时即可禁止缩放。

在代码中创建了【禁用/开启缩放】的按钮,点击按钮执行this.controls.enableZoom = !this.controls.enableZoom;即可切换禁用/开启缩放。

以上,就实现了禁止水平垂直旋转、平移、缩放的功能,至于代码中创建场景、相机等的代码就不一一说明了,代码中进行了很详细的注释。

完整代码

<template>
  <div class="item">
    <div id="THREE45">
      <div class="buttons">
        <el-button type="primary" @click="clickEnabled"
          >{{
            this.controls && this.controls.enabled ? "禁用" : "开启"
          }}轨道控制器</el-button
        >
        <el-button type="primary" @click="clickEnableRotate"
          >{{
            this.controls && this.controls.enableRotate ? "禁用" : "开启"
          }}水平/垂直旋转</el-button
        >
        <el-button type="primary" @click="clickEnablePan"
          >{{
            this.controls && this.controls.enablePan ? "禁用" : "开启"
          }}平移</el-button
        >
        <el-button type="primary" @click="clickEnableZoom"
          >{{
            this.controls && this.controls.enableZoom ? "禁用" : "开启"
          }}缩放</el-button
        >
      </div>
    </div>
  </div>
</template>

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

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

export default {
  data() {
    return {
      camera: null,
      scene: null,
      dracoLoader: null,
      renderer: null,
      controls: null,
    };
  },
  mounted() {
    this.dracoLoader = new DRACOLoader();
    this.dracoLoader.setDecoderPath("js/libs/draco/");
    this.dracoLoader.setDecoderConfig({ type: "js" });
    this.initScene(); // 创建场景
    this.initCamera(); // 创建相机
    this.initLight(); // 创建灯光
    this.initRenderer(); // 创建渲染器
    this.initControls(); //创建轨道控制器
    this.initGround(); // 创建地面
    this.initModel(); // 加载模型
  },
  methods: {
    initScene() {
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0x000000); // 设置场景背景颜色
    },
    initCamera() {
      this.camera = new THREE.PerspectiveCamera(
        35,
        (window.innerWidth - 201) / window.innerHeight,
        1,
        500
      ); // 透视相机
      this.camera.position.x = 0.5;
      this.camera.position.y = 0.5; // 设置相机的位置
      this.camera.position.z = 1.8;
      this.scene.add(this.camera); // 将相机添加到场景中
    },
    initLight() {
      const light = new THREE.DirectionalLight(0xffffff); // 平行光
      light.position.set(0.5, 1.0, 0.5).normalize(); // 设置平行光的方向,从(0.5, 1.0, 0.5)->target一般(0, 0, 0)
      this.scene.add(light); // 将灯光添加到场景中

      const ambLight = new THREE.AmbientLight(0xf0f0f0, 0.1); // 环境光
      this.scene.add(ambLight);
    },
    initRenderer() {
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.outputEncoding = THREE.sRGBEncoding;
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize(window.innerWidth - 201, window.innerHeight);
      document.getElementById("THREE45").appendChild(this.renderer.domElement);
    },
    initControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.addEventListener("change", this.render);
      this.controls.target.set(0, 0.1, 0);
    },
    initGround() {
      const ground = new THREE.Mesh(
        new THREE.BoxGeometry(1, 0.0015, 1),
        new THREE.MeshPhongMaterial({
          color: 0x999999,
          depthWrite: false,
          transparent: true,
          opacity: 1,
        })
      );
      ground.receiveShadow = true;
      this.scene.add(ground);
    },
    initModel() {
      this.dracoLoader.load("/models/models/draco/bunny.drc", (geometry) => {
        geometry.computeVertexNormals();

        const material = new THREE.MeshStandardMaterial({
          color: 0xffffff,
        });
        let mesh = new THREE.Mesh(geometry, material);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        mesh.position.y = -0.035;
        this.scene.add(mesh);

        this.dracoLoader.dispose();

        this.animate();
      });
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.render();
    },
    render() {
      this.renderer.render(this.scene, this.camera);
    },
    clickEnabled() {
      this.controls.enabled = !this.controls.enabled;
    },
    clickEnableRotate() {
      this.controls.enableRotate = !this.controls.enableRotate;
    },
    clickEnablePan() {
      this.controls.enablePan = !this.controls.enablePan;
    },
    clickEnableZoom() {
      this.controls.enableZoom = !this.controls.enableZoom;
    },
  },
};
</script>

<style lang="less" scoped>
.buttons {
  position: absolute;
  top: 20px;
  right: 20px;
}
</style>

写在最后

以上就是所有的代码和说明。