tree.js 在vue中的应用

798 阅读2分钟

1. 安装

npm i -s three

2.在vue中使用

最好是在vue2.x版本中使用,我在vue3.x版本使用,总是报错误。 以下代码都是在vue 2.6.11版本的下运行的

<template>
<div>
  <div id="container"></div>
</div>
</template>

<script>
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import json from "@/assets/02.json";
export default {
  name: "THREETest",
  data() {
    return {
      // 相机
      camera: null,
      // 场景
      scene: null,
      // 渲染器
      renderer: null,
      // 几何体
      mesh: null,
      // 鼠标控制
      controls: null,
    };
  },

  methods: {
    init: function () {
      //创建场景对象Scene
      this.scene = new THREE.Scene();
      // 获取根容器
      let container = document.getElementById("container");
      /**
       * 正投影相机设置
       */
      var width = container.clientWidth; //窗口宽度
      var height = container.clientHeight; //窗口高度
      var k = width / height; //窗口宽高比
      var s = 400; //三维场景显示范围控制系数,系数越大,显示的范围越大
      //创建相机对象
      this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s + 100);
      this.camera.position.set(0, -600, 200); //设置相机位置
      this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)

      //创建渲染器对象
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      this.renderer.setSize(container.clientWidth, container.clientHeight); //设置渲染区域尺寸
      this.renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      container.appendChild(this.renderer.domElement); //body元素中插入canvas对象

      //辅助三维坐标系AxisHelper
      this.axisHelper = new THREE.AxisHelper(250);
      this.scene.add(this.axisHelper);

      // 地图数据
      let mapData = json.geometry.coordinates[0];
      // 声明一个空数组,来存放用来生成的点
      let points = [];
      // 转化为Vector2构成的顶点数组
      mapData.forEach((elem) => {
        // 这里我把坐标都缩小100倍
        points.push(new THREE.Vector2(elem[0] / 100, elem[1] / 100));
      });
      // 样条曲线生成更多的点
      var SplineCurve = new THREE.SplineCurve(points);
      var shape = new THREE.Shape(SplineCurve.getPoints(300));

      //拉伸造型,把二维平面拉伸成立体的
      let geometry = new THREE.ExtrudeGeometry(
        shape, //二维轮廓
        //拉伸参数
        {
          amount: 12, //拉伸长度
          bevelEnabled: false, //无倒角
        }
      );
      //  给几何体设置贴纸
      var texture1 = new THREE.TextureLoader().load(
        "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2170086043,2766494990&fm=26&gp=0.jpg"
      );
      // 立即使用纹理进行材质创建
      var material1 = new THREE.MeshBasicMaterial({
        map: texture1,
      });

      var mesh1 = new THREE.Mesh(geometry, material1); //网格模型对象Mesh
      this.scene.add(mesh1); //点模型添加到场景中

      /**
       *设置光源
       */
      var point = new THREE.PointLight(0xcccccc); //代表模型的亮度
      point.position.set(100, 100, 100); //点光源位置
      this.scene.add(point); //点光源添加到场景中

      // 加载图片
      var textureTree = new THREE.TextureLoader().load("s.png");
      // 批量创建表示一个树的精灵模型
      for (let i = 0; i < 100; i++) {
        var spriteMaterial = new THREE.SpriteMaterial({
          map: textureTree, //设置精灵纹理贴图
        });
        // 创建精灵模型对象
        var sprite = new THREE.Sprite(spriteMaterial);
        this.scene.add(sprite);
        // 控制精灵大小,
        sprite.scale.set(30, 30, 1); //// 只需要设置x、y两个分量就可以
        var k1 = Math.random() - 0.5;
        var k2 = Math.random() - 0.5;
        // 设置精灵模型位置,在xoz平面上随机分布
        sprite.position.set(500 * k1, 600 * k2, 20);
      }
    },
    render: function () {
      // 浏览器 动画 默认每秒60次
      requestAnimationFrame(this.render); //请求再次执行渲染函数render
      this.renderer.render(this.scene, this.camera); //执行渲染操作
    },
    // 创建控件对象
    createControls() {
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    },
  },
  // 虚拟dom挂载后加载
  mounted() {
    this.init();
    this.render();
    this.createControls();
  },
};
</script>

<style scoped>
#container {
  height: 700px;
}
</style>


效果如下:

3. 封装tree.js,便于以后调用

  • camera 相机
  • scene 场景
  • renderer渲染器
  • point光源

我们来根据这基本的参数来封装一个基本的map类

1.新建map.js
2.引入tree.js

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

3.创建一个类,并导出

class Map {
}
export default Map

4.初始化这类

class Map {
  camera = null//相机
  scene = null//场景
  renderer = null//渲染对象
  controls = null//控制对象
 constructor(container) {
     //这个是要加载的容器
    this.container = container
  }
  // 初始化方法
  init() {
    //将容器赋值给container
    let container = this.container
    /**
     * 创建场景对象Scene
     */
     
    /**
    * 创建网格模型
    */
    // var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
    let geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
    let material = new THREE.MeshLambertMaterial({
      color: 0x0000ff
    }); //材质对象Material
    var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
    this.scene.add(mesh); //网格模型添加到场景中
    this.scene = new THREE.Scene();
    /**
       * 光源设置
       */
    //点光源
    var point = new THREE.PointLight(0xcccccc); //代表模型的亮度
    point.position.set(0, -600, 200); //点光源位置
    this.scene.add(point); //点光源添加到场景中
    //环境光
    var ambient = new THREE.AmbientLight(0x444444);
    this.scene.add(ambient);
    /**
     * 相机设置
     */
    var width = container.clientWidth; //窗口宽度
    var height = container.clientHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 400; //三维场景显示范围控制系数,系数越大,显示的范围越大
    //创建相机对象 
    // 正向投影
    this.camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s + 100);
    this.camera.position.set(0, -400, 200); //设置相机位置
    this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
    //辅助三维坐标系AxisHelper
    this.axisHelper = new THREE.AxisHelper(250);
    this.scene.add(this.axisHelper);
    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

    this.renderer.setSize(width, height); //设置渲染区域尺寸
    //设置背景颜色,我这里设置的是透明色
    this.renderer.setClearColor(0xEEEEEE, 0.0);
    container.appendChild(this.renderer.domElement); //body元素中插入canvas对象
  }
  //定义渲染函数
  render = () => {
    requestAnimationFrame(this.render); //请求再次执行渲染函数render
    this.renderer.render(this.scene, this.camera);//执行渲染操作
  }
  //初始化,鼠标控件
  createControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    // this.controls.addEventListener("change", this.test);
  }
}
  1. 在组件中使用
<template>
<div class="home">
  <div id="maps"></div>
</div>
</template>

<script>

import Map from "@/utils/map.js";

export default {
  data() {
    return {
      map: null,
    };
  },

  mounted() {
    this.init();  
  },
  methods: {
    init() {
      let container = document.getElementById("maps");
      this.map = new Map(
        container, 
      );
      this.map.init();
      this.map.render();
      this.map.createControls();
    },
  }
};
</script>

<style scoped>
.home {
  width: 100%;
  height: 100%;
  background-color: #a9a9a9;
}

#maps {
  height: 700px;
}
</style>

效果如下: 现在tree.js第一篇就到这,tree.js的文档地址www.webgl3d.cn/,下一片我们学习,室内…