vue项目使用three.js轨道控制器OrbitControls.js渲染VR2D360度图片

vue项目使用three.js轨道控制器OrbitControls.js渲染VR2D360度图片

上一篇博客是用浏览器监听事件来控制图片的render,随着项目的深入,发现three.js-master源码里有几种控制器,例如: OrbitControls、TrackballControls ,通过使用可以精简很多代码,本篇只讲OrbitControls.js。
当前demo使用的three.js为0.115.0版本
项目中安装three

npm install three

安装完成再组件如下导入:

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

html文件中写入如下代码图片预览容器,代码如下:

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

script脚本中如下代码:

data() {
    return {
      /** VR图片预览start */
      camera: null,
      scene: null,
      renderer: null,
      group: [], // 相机 热点通过射线与球面的交点绘制的几何体集合
      controls: null,
      mesh: {},
      radius: 500 // 球几何体半径
      /** VR图片预览end */
    }
  },
  methods: {
    init() {
      let textureLoader = new THREE.TextureLoader(); // 纹理
      textureLoader.load("static/img/blank.png", (texture) => {
        texture.mapping = THREE.UVMapping;

        this.initImg(texture);
        this.animate(); // 动画
      });
    },
    initImg(texture) {
      let container = this.$refs.container;
      // 容器宽度、高度
      let containerWidth = container.offsetWidth;
      let containerHeight = container.offsetHeight;
      this.renderer = new THREE.WebGLRenderer({ antialias: true }); // 需要使用WebGLRenderer
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize(containerWidth, containerHeight);
     container.appendChild(this.renderer.domElement);

      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(60, containerWidth / containerHeight, 1, 1000);
      this.mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(this.radius, 32, 16), new THREE.MeshBasicMaterial({ map: texture }));
      this.mesh.geometry.scale(-1, 1, 1);
      this.scene.add(this.mesh);

      this.group = new THREE.Group();
      this.scene.add(this.group);

      let position = new THREE.Vector3(100, 6.123233995736766e-15, 0); // 创建相机初始位置
      this.camera.position.set(position.x, position.y, position.z);
      this.controls = new OrbitControls(this.camera, container );
      this.controls.minDistance = 18; // 相机最近
      this.controls.maxDistance = 500; // 相机最远
      this.controls.autoRotate = true; // 图片自动旋转
      this.controls.autoRotateSpeed = 0.8; // 阻尼系数
    
      var axesHelper = new THREE.AxesHelper(500) // 三维坐标辅助线
      this.scene.add(axesHelper)
      window.addEventListener('resize', this.onWindowResize, false); // 渲染图片区域resize
    },
    onWindowResize() {
      this.camera.aspect = this.$refs.container.offsetWidth / this.$refs.container.offsetHeight;
      this.camera.updateProjectionMatrix();

      this.renderer.setSize(this.$refs.container.offsetWidth, this.$refs.container.offsetHeight);
    },
    animate() {
      this.requestAnimationId = requestAnimationFrame(this.animate);
      this.controls.update(); // required when damping is enabled
      this.renderer.render(this.scene, this.camera);
    }
  }

关闭当前页面需要关闭当前页面的EventListener事件,以及添加到scene中的mesh,不然一直在浏览器内存中,很耗浏览器性能,可以调用如下方法

dispose() {
	if (this.controls !== null) {
        this.controls.dispose();
        this.scene.remove(this.group);
     }
}

this.controls.dispose(),轨道控制dispose在插件中实现的代码如下:

this.dispose = function () {
    scope.domElement.removeEventListener('contextmenu', onContextMenu, false)
    scope.domElement.removeEventListener('mousedown', onMouseDown, false)
    scope.domElement.removeEventListener('wheel', onMouseWheel, false)

    scope.domElement.removeEventListener('touchstart', onTouchStart, false)
    scope.domElement.removeEventListener('touchend', onTouchEnd, false)
    scope.domElement.removeEventListener('touchmove', onTouchMove, false)

    document.removeEventListener('mousemove', onMouseMove, false)
    document.removeEventListener('mouseup', onMouseUp, false)

    scope.domElement.removeEventListener('keydown', onKeyDown, false)

    // scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
  }

当我们用到window或dom的addEventListener事件时,如果不销毁,监听事件每次执行都会被调用,并不会覆盖上一次的事件,这就导致一些你可能意识不到的bug

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值