vue+threejs写应用:复制粘贴状态

82 阅读1分钟

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


写在前面

本文使用vue+threejs写应用:复制粘贴状态,当我们的模型转到一个适合展示角度的时候,我们可以复制当前界面,继续展示模型,然后想要恢复刚刚复制的界面的时候,我们可以粘贴状态,就恢复到刚刚复制的界面。

代码说明

首先是html的编写,一个id容器,两个按钮,分别用来复制当前状态和粘贴状态。

接着是引入threejs和需要的模块。

然后是相机camera、场景scene、gltf模型加载器gltfLoader、场景渲染器renderer、灯光light、轨道控制器controls的创建,创建的方法在mounted()中调用,具体怎么创建的可以看代码,代码中进行了详细的注释。

创建完后的界面是这样的:

image.png

给【复制当前状态】按钮添加点击事件clickSaveState(),点击后执行this.controls.saveState();即复制了当前的界面。

给【粘贴状态】按钮添加点击事件clickReset(),点击后执行this.controls.reset();即粘贴了复制的界面。

由threejs的轨道控制器模块提供的.saveState()和.reset()方法,可以实现状态的复制和粘贴。

完整代码

<template>
  <div class="item">
    <div id="THREE45">
      <div class="buttons">
        <el-button type="primary" @click="clickSaveState"
          >复制当前状态</el-button
        >
        <el-button type="primary" @click="clickReset">粘贴状态</el-button>
      </div>
    </div>
  </div>
</template>

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

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

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

export default {
  data() {
    return {
      camera: null,
      scene: null,
      gltfLoader: null,
      renderer: null,
      controls: null,
    };
  },
  mounted() {
    this.gltfLoader = new GLTFLoader();
    this.initScene(); // 创建场景
    this.initCamera(); // 创建相机
    this.initLight(); // 创建灯光
    this.initRenderer(); // 创建渲染器
    this.initControls(); //创建轨道控制器
    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);
    },
    initModel() {
      this.gltfLoader.load("/models/models/gltf/shiba/scene.gltf", (gltf) => {
        gltf.scene.scale.set(0.5, 0.5, 0.5);

        this.scene.add(gltf.scene);

        this.animate();
      });
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.render();
    },
    render() {
      this.renderer.render(this.scene, this.camera);
    },
    clickSaveState() {
      this.controls.saveState();
    },
    clickReset() {
      this.controls.reset();
    },
  },
};
</script>

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

写在最后

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