4***@qq.com
4***@qq.com
  • 发布:2023-09-14 15:06
  • 更新:2023-09-14 15:06
  • 阅读:542

使用renderjs 加载three.js模型的时候,如果模型还没有加载完就退出当前页面,会造成整个APP卡顿

分类:uni-app
<template>  
    <view class="">  
        <view :prop="threeData" :change:prop="threeModule.getNfrUrl" :clearFlag="clearFlag" :change:clearFlag="threeModule.clear">  
        </view>  
        <view ref="threeView" id="threeView" class="three" >  
            <!-- <u-loading-page class="aaa" mode="circle" loadingText="加载中" :loading="true" bgColor="transparent"></u-loading-page> -->  
        </view>  
    </view>  
</template>  
<script>  
    export default {  
        props:{  
            modelUrl:{  
                type: String,  
                default: ''  
            },  
            changeFlag:{  
                type: Boolean,  
                default: true  
            },  
        },  
        data(){  
            return {  
                threeData: {  
                    changeFlag: true,  
                    modelUrl: '',  
                },  
                clearFlag: false,  
            }  
        },  
        methods: {  
            onload(){  
                uni.hideLoading()  
            },  
            clear(){  
                uni.hideLoading()  
                this.clearFlag = true  
            }  
        },  
        // beforeDestroy(){  
        //  this.threeData = {  
        //      ...this.threeData,  
        //      clearFlag: 'aaaa'  
        //  }  
        //  this.clearFlag = true  
        //  console.log('beforeDestroy2')  
        // },  
        watch: {  
            modelUrl:{  
                handler(val){  
                    if (val) {  
                        let routes = getCurrentPages()  
                        let curRoute = routes[routes.length - 1].route  
                        uni.showLoading({  
                            title: '3D模型加载中...',  
                            mask: true,  
                        })  
                        if (curRoute == 'pageA/home/hcpDetails/index') {  
                            this.threeData = {  
                                changeFlag: false,  
                                modelUrl: val,  
                            }  
                        } else {  
                            this.threeData = {  
                                changeFlag: true,  
                                modelUrl: val,  
                            }  
                        }  
                    }  
                },  
                immediate: true,  
            },  
        }  
    }  
</script>  
<script module="threeModule" lang="renderjs">  
    import * as THREE from 'three'  
    import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'  
    import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';  
    import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js';  
    export default {  
        data() {  
            return {  
                camera: null,  
                scene: null,  
                renderer: null,  
                controls: null,  
                clock: null,  
                timeS: 0,  
                modelUrl: '',  
                changeFlag: true,  
                ownerInstance: null  
            }  
        },  
        methods: {  
            clear(newValue){  
                cancelAnimationFrame(this.animate)  
                this.renderer.forceContextLoss()  
                this.renderer.dispose()  
                this.scene.clear()  
                this.scene = null  
                this.camera = null  
                this.controls = null  
                this.renderer.domElement = null  
                this.renderer = null  
            },  
            getNfrUrl(newValue, oldValue, ownerInstance){  
                this.modelUrl = newValue.modelUrl  
                this.changeFlag = newValue.changeFlag  
                this.ownerInstance = ownerInstance  
                this.init()  
                // this.$nextTick(() => {  
                // })  
            },  
            init() {  
                // 创建一个场景  
                this.scene = new THREE.Scene()  
                //三位坐标线  
                // const axesHelper = new THREE.AxesHelper(5);  
                // this.scene.add(axesHelper);  
                /**相机设置*/  
                var width = window.innerWidth; //窗口宽度  
                var height = window.innerHeight; //窗口高度  
                // var k = width / height; //窗口宽高比  
                var k = 345 / 400     
                var s = 380; //三维场景显示范围控制系数,系数越大,显示的范围越大  
                //创建相机对象,45是相机的视角  , 宽高比是屏幕的宽高比 , 最近能看到0.1 , 最远能看到10000  
                // this.camera = new THREE.OrthographicCamera(-s * k, s * k, s , -s, 1, 1000);  
                // this.camera.position.set(0, 20, 300);  
                this.camera = new THREE.PerspectiveCamera()  
                //100,300 ,500  
                this.camera.position.set(500, 0, 700); //设置相机位置  
                // this.camera.position.set(100, -800, 500);  
                // this.scene.position.set(0,40,0)  
                console.log(this.scene.position)  
                this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)  

                /* 光源设置*/  
                this.pointLight()  
                this.gblLoader()  
                let fileName = this.modelUrl.lastIndexOf(".")  
                let fileFormat = this.modelUrl.substring(fileName + 1, this.modelUrl.length).toLowerCase()  
                if (fileFormat == 'fbx') {  
                    this.fbxLoader()  
                } else if(fileFormat == 'glb') {  
                    this.gblLoader()  
                }  
                this.clock = new THREE.Clock()  
                //导入模型文件  
                // this.gblLoader()  
                // this.objLoader()  

                // 执行一个渲染函数  
                this.rendererGLR()  
                //创建控件对象  
                this.change()  
                //更新轨道控件  
                this.animate()  
            },  
            //导入FBX模型文件  
            fbxLoader(){  
                let that=this  
                const loader = new FBXLoader();  
                loader.load(this.modelUrl,function(mesh){  
                    that.scene.add(mesh);  
                    that.ownerInstance.callMethod('onload')  
                })  
            },  
            //导入GLB模型文件  
            gblLoader(){  
                console.log(1111)  
                let that=this  
                const loader = new GLTFLoader();  
                loader.load(this.modelUrl, function(gltf) {  
                    console.log(gltf)  
                    that.mesh = gltf.scene  
                    let model = gltf.scene  
                    that.scene.add(model);  
                    that.ownerInstance.callMethod('onload')  
                });  
            },  
            //渲染函数  
            rendererGLR(){   
                this.$nextTick(() => {  
                    const element = document.getElementById('threeView')  
                    this.renderer.setSize(element.clientWidth, element.clientHeight);  
                    element.appendChild(this.renderer.domElement);  
                })  
                this.renderer = new THREE.WebGLRenderer({alpha:true, antialias: true});//alpha:true背景透明  
                this.renderer.setPixelRatio( window.devicePixelRatio * 2);  
                this.renderer.toneMapping = THREE.ACESFilmicToneMapping;  
                this.renderer.toneMappingExposure = 1.0;  
                this.renderer.shadowMap.enabled = true;  
                this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;  
                // // #ifdef H5  
                // // #endif  
                // // #ifdef APP-PLUS  
                // this.$refs.threeView.appendChild(this.renderer.domElement);  
                // // #endif  
                this.renderer.render(this.scene, this.camera);  
            },  
            //光源设置  
            pointLight(){  
                let ambientLight = new THREE.AmbientLight(0xffffff,1);  
                this.scene.add(ambientLight);  
                const directional_light = new THREE.DirectionalLight( 0xffffff, 1 );  
                directional_light.position.set( 0, 1, 0 );   
                directional_light.castShadow = true;   
                this.scene.add(directional_light);  
                let a=1,b=0.6,c=10;  
                let directionalLight1 = new THREE.DirectionalLight(0xffffff,b);  
                directionalLight1.position.set(-a,-a ,a*c).normalize();  
                let directionalLight2 = new THREE.DirectionalLight(0xffffff,b);  
                directionalLight2.position.set(a,-a,-a*c).normalize();  
                let directionalLight3 = new THREE.DirectionalLight(0xffffff,b);  
                directionalLight3.position.set(-a,a,-a*c).normalize();  
                let directionalLight4 = new THREE.DirectionalLight(0xffffff,b);  
                directionalLight4.position.set(a,a,a*c).normalize();  
                this.scene.add(directionalLight1);  
                this.scene.add(directionalLight2);  
                this.scene.add(directionalLight3);  
                this.scene.add(directionalLight4);  
            },  
            //创建控件对象  
            change(){  
                this.controls = new OrbitControls(this.camera, this.renderer.domElement);  
                this.controls.minDistance = 300  
                this.controls.maxDistance  = 1000  
                this.controls.addEventListener('change', () => {  
                    this.renderer.render(this.scene, this.camera);  
                }); //监听鼠标、键盘事件  
                //禁止缩放  
                this.controls.enableZoom = this.changeFlag  
                //禁止旋转  
                this.controls.enableRotate = this.changeFlag  
                //禁止右键拖拽  
                this.controls.enablePan  = this.changeFlag  
            },  
            //更新轨道控件  
            animate() {  
                // this.controls.update();  
                // this.renderer.render(this.scene, this.camera);  
                // requestAnimationFrame(()=>{  
                //  this.animate()  
                // });  
                if (this.renderer) {  
                    // console.log(this.stats)  
                    // this.stats.update()  
                    let T = this.clock.getDelta()  
                    let renderT = 1 / 30  
                    this.timeS = this.timeS + T  
                    if(this.timeS > renderT) {  
                        this.controls.update();  
                        this.renderer.render(this.scene, this.camera);  
                        this.timeS = 0  
                    }  
                    requestAnimationFrame(this.animate);  
                    if (!this.changeFlag) {  
                        this.controls.autoRotateSpeed = 15  
                    }  
                    this.controls.autoRotate = true // 是否自动旋转  
                }  
                //创建一个时钟对象  
                // this.clock = new THREE.Clock()  
                // this.scene.rotateY(0.01)  
                //获得两帧的时间间隔  更新混合器相关的时间  
                // if (this.mixer) {this.mixer.update(this.clock.getDelta())}  
            },  
        },  
        // watch: {  
        //  modelUrl:{  
        //      handler(val){  
        //              console.log(88)  
        //              console.log(val.toString())  
        //          if (val) {  
        //              this.init()  
        //          }  
        //      },  
        //      immediate: true,  
        //  }  
        // }  
    }  
</script>  
<style scoped>   
    .three{  
        width: 100%;  
        height:690rpx;  
    }  
</style>  
2023-09-14 15:06 负责人:无 分享
已邀请:

要回复问题请先登录注册