1***@qq.com
1***@qq.com
  • 发布:2025-09-28 17:46
  • 更新:2025-09-28 17:46
  • 阅读:11

关于uni-app 在vue3版本下在renderjs引入three.js使用报错TypeError: ‘get‘ on proxy: property ‘modelViewMatrix‘的解决方法

分类:uni-app

标题

  • 关于uni-app 在vue3版本下在renderjs引入three.min.js使用renderer.render(scene, camera);报错TypeError: ‘get‘ on proxy: property ‘modelViewMatrix‘ is a read-only and non-configurable data property的解决方法

问题描述

  • 我在uni-app vue3版本下在renderjs中引入three.min.js,实现360全景视频播放,播放功能是封装好的,在vue2版本下是能正常使用的,但在vue3版本下会报错TypeError: ‘get‘ on proxy: property ‘modelViewMatrix‘ is a read-only and non-configurable data property........
  • 在网上搜索,发现是vue3的proxy的锅,因为three.js内部一些变量使用Object.defineProperty来定义的,这样就被vue3抓到了,给处理成成了响应式,但three.js内部自有一套变量响应,导致冲突,大概原因就是这样具体看这里

    网上传的解决办法

  • 都说是不要在data函数或者用reactive定义变量来存储three实例化后的对象,直接用全局变量接收,比如:
//这样是错误的,会导致报错  
let data = reactive({  
  scene: null  
})
//正确的定义方法  
let scene = null
  • 这种方法行不行,我也不清楚,因为renderjs是不支持组合api语法的,而且我是使用封装的类来调用three.js的,根本没用vue的变量接收实例化对象,所以这种方式对我没用

尝试解决办法

  • 我在找资料时,无意间看到一篇文章Bpmn.js 使用【问题?解决】,虽然和three.js无关,但好像和我的问题有点类似,他的解决方法为:
    // 我的解决是:引入Modeler的文件,importXML时 modeler使用toRaw包一下。并且在使用modeling.updateProperties更新元素属性时,将this.element也使用toRaw包一下:toRaw(this.element)  
    updateProperties(properties) {  
     const modeling = toRaw(this.modeler).get("modeling");  
     modeling.updateProperties(toRaw(this.element), properties);  
    }
  • 于是我也尝试引入vue3的toRaw在render的时候包裹一下:
    //在renderjs下引入toRaw   
    import { toRaw } from 'vue'  
    export default {  
    mounted () {  
    window.toRaw = toRaw//需要挂载到window对象上,不然类里面调用不到  
    }  
    }
    //在我的类里面,调用toRaw  
    const scene = window.toRaw ? window.toRaw(this.secne) : this.scene  
    this.renderer.render(scene, this.camera);
  • 该方式确实可以解决我的问题,但只支持h5,因为在app vue3 renderjs下使用import { toRaw } from 'vue',会报错could not resolve ‘vue’,这下就卡住了。

最终解决办法

  • 既然toRaw在app当中引入不了,那我自己实现一个toRaw行不行?说干就干,定位到toRaw的源码,发现结构为:
    function toRaw (observed) {  
    const raw = observed && observed["__v_raw"]  ? observed["__v_raw"] : observed  
    return raw ? toRaw(raw) : observed   
    }
  • 意外是个很简单的代码,判断传入的值有没有__v_raw属性,如果有返回该属性值,如果没有返回传入的值
  • 这样解决起来就很简单了:
    const scene = this.scene["__v_raw"] ? this.scene["__v_raw"] : this.scene  
    this.renderer.render(scene, this.camera);
  • 这样app和h5都没问题了
0 关注 分享

要回复文章请先登录注册