关于使用threeJs开发3d应用的相关爬坑记录

31 篇文章 0 订阅
8 篇文章 1 订阅

问题一:
关于使用轨道控制器:THREE.OrbitControls 出现的问题。

问题描述:
当场景使用轨道控制器后,致使页面中的输入框或单选或复选按钮全部失效的问题

分析问题原因:
该问题是由于轨道控制器的工作原理造成的,当模型不是全屏状态(body中)渲染,而是在局部渲染时会出现该问题。

解决办法是:

// 第二个参数默认为body 如果您的场景是局部渲染的,请确保使用它(即渲染场景的容器)
controls = new THREE.OrbitControls(that.camera, that.renderer.domElement);

问题二:
关于模型点击事件的问题

问题描述
当点击场景中的模型时,点击的位置不准确的问题

分析问题原因:
场景渲染的问题造成的,在threeJs中事件的点击是通过,发射二维射线,并检查射线和物体之间是否有相交点来完成的。

解决办法是:

addEventListener('click', function(event) {
  let mouse = new THREE.Vector2(); // 定义二维射线
  /** 如果模型是在全屏模式下渲染的(渲染在body中),可以用下面的两行代码 */
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
  /** 获取点击点位于射线上的位置,值在-1和1之间,此写法适用于模型不在全屏下渲染的场景中(页面局部渲染) */
  mouse.x = ((event.clientX - mainCanvas.getBoundingClientRect().left) / mainCanvas.offsetWidth) * 2 - 1;
  mouse.y = -((event.clientY - mainCanvas.getBoundingClientRect().top) / mainCanvas.offsetHeight) * 2 + 1;
})

问题三:
关于模型点击事件造成当前页面或其他页面的图片上传按钮失效的问题

问题描述
加载过3d场景后,图片上传按钮点击无效

分析问题原因:
事件的默认行为:event.preventDefault()

解决办法是:

addEventListener('click', function(event) {
  event.preventDefault(); // 阻止默认点击行为,请不要使用它
})

问题四:
加载3d场景页面越来越卡顿的问题

问题描述
当多次加载3d场景,由于资源一直占用内存久而久之造成内存泄漏,而造成页面越来越卡顿

分析问题原因:
资源占用,导致内存泄漏

解决办法是:
清空资源加载,释放内存

  1. 将使用到的 scene, camera, gemotry, material, texture 的 dispose 释放内存
  2. 由于render渲染器处于一直执行渲染的状态,及时暂停渲染器 requestAnimationFrame() 的运行
  3. 降低渲染频率
  4. 缩小模型大小,可以简化模型的制作,或采用draco压缩模型,使用方法请看博主的另一篇文章 draco压缩模型的爬坑记录
// 这种方式可以有效的利用计算机资源,但是比价耗费性能
function render() {
  // 记录当前处于那个渲染数
  // requestAnimationFrame 默认16.7ms调用一次render函数,一秒大约调用60次
  this.requestAnimationId = requestAnimationFrame(render);
  this.renderer.render(that.scene, that.camera);
}
render()

通过时间判断来降低renderer.render执行频率

var FPS = 14;
var renderT = 1 / FPS; // 间隔多长时间渲染一次,单位秒
// 声明一个变量表示render()函数被多次调用的累积时间
// 执行一次renderer.render,timeS重新置0
var timeS = 0;
function render() {
  // 记录当前处于那个渲染数
  // requestAnimationFrame 默认16.7ms调用一次render函数,一秒大约调用60次
  this.requestAnimationId = requestAnimationFrame(render);
  // .getDelta()方法获得两帧的时间间隔
  var T = clock.getDelta();
  timeS = timeS + T;
  if (timeS > renderT) {
    // 执行渲染操作,每执行一次,timeS置0
    that.renderer.render(that.scene, that.camera);
    timeS = 0;
  }
}
render()

释放内存中的资源

clearCache() {
  if (this.scene) { // 清除scene
     var sceneObj = this.scene.children
     sceneObj.forEach((item) => {
       item.children = []
       if (item.material) {
           item.material = null
       }
       if (item.geometry) {
           item.geometry = null
       }
    })
 };
 if(this.AllGroup) { // 清除group组
    let groupChild = this.AllGroup.children
    groupChild.forEach((item) => {
       item.children = []
    })
 };
 if(this.renderer) { // 清除渲染器缓存
   this.renderer.dispose()
   this.renderer.clearColor()
   this.renderer.clearDepth()
   this.renderer.clearStencil()
   this.renderer.forceContextLoss()
   this.renderer.renderLists.dispose()
   this.renderer.context = null
   this.renderer.domElement = null
 };
 if(this.controls) { // 清楚轨道控制器
   this.controls.dispose()
   this.controls = null
 };
 if(this.composer) { // 清除效果组合器
   this.composer.passes = []
   this.composer.copyPass = null
   this.composer.renderer.dispose()
 };
 if(this.renderPass) { // 清除渲染通道
   this.renderPass.camera = null
   this.renderPass.scene.children = []
 };
 if(this.OutlinePass) { // 清除轮廓线
   this.OutlinePass.camera = null
   this.OutlinePass.scene.children = []
 };
 this.scene = null
 this.camera = null
 this.twoLine = null
 this.renderer = null
 this.renderPass = null
 this.OutlinePass = null
}

// 在页面卸载时或重新加载场景时调用 clearCache 方法

beforeDestroy() {
  // 页面卸载前清除内存,定时器,渲染器等
  cancelAnimationFrame(this.requestAnimationId);
  this.clearCache();
  new THREE.Cache.clear()
}

以上便是我在开发中遇到的一些问题,在此记录下来,以后有其他问题会持续更新…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值