先看效果:

<template>
  <div>
    <el-container>
      <el-main>
        <div class="box-card-left">
          <div id="threejs" style="border: 1px solid red"></div>
          <div class="box-right">
            <pre style="font-size: 16px"></pre>
            <el-button type="primary" @click="start">开始漫游</el-button>
            <el-button type="primary" @click="end">结束漫游</el-button>
          </div>
        </div>
      </el-main>
    </el-container>
  </div>
</template>
<script>
import Drawer from "@/components/Drawer.vue";
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
export default {
  components: { Drawer },
  data() {
    return {
      name: "",
      cameraX: 200,
      cameraY: 200,
      cameraZ: 200,
      scene: null,
      camera: null,
      renderer: null,
      mesh: null,
      mesh_sun: null,
      geometry: null,
      group: null,
      axis: null,
      texture: null,
      loader: null,
      animationId: null,
      line: null,
      lineFlag: true,
      circleFlag: true,
      catmullRowCurve3: null,
      controls: null,
      request: null,
      r: 300,
      angle: 0,
      i: 0,
      points:[]
    };
  },
  created() {},
  mounted() {
    this.name = this.$route.query.name;
    this.init();
  },
  methods: {
    end(){
      window.cancelAnimationFrame(this.request)
    },
    goBack() {
      this.$router.go(-1);
    },
    start() {
      this.points = this.catmullRowCurve3.getPoints(220);
      this.render();
    },
    render() {
      if(this.i < this.points.length-1) {
        this.camera.position.copy(this.points[this.i]);
        this.camera.lookAt(this.points[this.i+1]);
        this.camera.updateProjectionMatrix();
        this.controls.target.copy(this.points[this.i+1]);
        this.controls.update();
        this.i++;
      } else {
        this.i = 0;
      }
      this.renderer.render(this.scene, this.camera);
      this.request = requestAnimationFrame(this.render);
    },
    // 管道漫游案例:首先创建一个管道;管道使用纹理贴图;获取管道的扫描线上的 n个点;相机固定在 i 点, lookAt i+1 点位置;
    init() {
      // 1,创建场景对象
      this.scene = new this.$three.Scene();
      // 创建缓存几何体对象
      this.geomery = new this.$three.BufferGeometry();
      // 通过 Vector3(x,y,z) 创建顶点数据
      var pointsArr = [
        new this.$three.Vector3(0, 0, 0),
        new this.$three.Vector3(100, 0, 0),
        new this.$three.Vector3(100, 0, 100),
        new this.$three.Vector3(0, 100, 100),
        new this.$three.Vector3(-50, 50, 50),
        new this.$three.Vector3(0, 0, 0),
      ];
      // 创建三维样条曲线对象(参数是三维点数组)
      this.catmullRowCurve3 = new this.$three.CatmullRomCurve3(pointsArr);
      // 获取三维样条曲线上的100个点
      const points = this.catmullRowCurve3.getPoints(220);
      // 设置缓存点模型的点数据
      this.geomery.setFromPoints(points);
      // 创建线材质对象
      this.material = new this.$three.LineBasicMaterial({ color: 0xaabb11 });
      // 创建线模型对象
      this.line = new this.$three.Line(this.geomery, this.material);
      this.scene.add(this.line);
      // 创建管道缓冲几何体
      const tubeGeometry = new this.$three.TubeGeometry(this.catmullRowCurve3, 104, 10, 36, false);
      // 创建网格材质对象
      const meshBasicMaterial = new this.$three.PointsMaterial({
        color: 0xbbddff,
        // side: this.$three.DoubleSide
      });
      const mesh = new this.$three.Points(tubeGeometry,meshBasicMaterial);
      this.scene.add(mesh);
      // 创建透视投影相机对象
      this.camera = new this.$three.PerspectiveCamera(90, 1, 0.01, 3000);
      this.camera.position.set(200, 200, 200);
      this.camera.lookAt(0, 0, 0);
      // 创建辅助坐标轴对象
      const axesHelper = new this.$three.AxesHelper(150);
      this.scene.add(axesHelper);
      // 创建渲染器对象
      this.renderer = new this.$three.WebGLRenderer();
      this.renderer.setSize(1000, 800);
      this.renderer.render(this.scene, this.camera);
      document.getElementById("threejs").appendChild(this.renderer.domElement);
      // 创建空间轨道控制器对象
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.addEventListener("change", () => {
        this.renderer.render(this.scene, this.camera);
      });
    },
  },
};
</script>
//
<style lang="less" scoped>
.msg {
  padding: 20px;
  text-align: left;
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
  .span {
    margin: 0 30px 30px 0;
    // white-space: nowrap;
  }
  .p {
    text-align: left;
  }
}
.box-card-left {
  display: flex;
  align-items: flex-start;
  flex-direction: row;
  width: 100%;
  .box-right {
    text-align: left;
    padding: 10px;
    .xyz {
      width: 100px;
      margin-left: 20px;
    }
    .box-btn {
      margin-left: 20px;
    }
  }
}
</style>
 



















