threejs加载stl模型在uniapp中的应用(打包安卓), 在template模版中直接读取renderjs的值比如 threeArea.modelFileLink 在安卓打包后会报错,但是在H5页面中可以正常读取,最后是通过ownerVm.callMethod('receiveRenderData', true); 传递给逻辑层解决的
在安卓系统中threejs通过renderjs才能显示在页面上,否则无法显示,但是在H5页面中可以不用renderjs,能正常读取
xml
<template>
<view>
<template v-show="progressLoading">
<view id="container"></view>
<view id="threeArea" :option="option" :change:option="threeArea.receiveInfo"></view>
<!-- <view style="position: absolute; top:0; left: 0; right: 0; height: 200rpx; background: #ff0;">
<image :src='imgLink' mode="heightFix" v-if="imgLink" style="width: 200rpx;"></image>
<view>{{ imgLink}}</view>
</view> -->
<view class="detail_btn" style="text-align: center;">
<u-button type="primary" class="detail_btns" @click="capture">截图并对比</u-button>
</view>
</template>
<template v-if="!progressLoading">
<view style="position: fixed; top: 0; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; align-items: center; background: rgba(0,0,0, .8); color: #fff">模型正在加载中 {{ progressNumber }}</view>
</template>
<u-modal title="" :show="popupShow" :showCancelButton="true" cancelText="返回" confirmText="去对比"
@cancel="popupShow=false" @confirm="gotoCamera">
<view class="popup_cont">
<image :src='imgLink' mode="heightFix"></image>
</view>
</u-modal>
</view>
</template>
<script>
import {
uploadFile
} from '@/api/upload.js'
export default {
data() {
return {
option: {
modelFile: null,
storedLines: null
},
popupShow: false,
imgLink: null,
progressLoading: false,
progressNumber: '0%',
};
},
mounted() {
const storedLines = uni.getStorageSync('lines');
this.option.storedLines = storedLines || []
},
onLoad(options) {
this.option.modelFile = this.$imgUrl + options.modelFile
console.log('this.option.modelFile :', this.option.modelFile );
uni.setNavigationBarTitle({
title: options.modelTitle
})
},
methods: {
capture() {
// this.popupShow = true;
this.getImage('album');
},
gotoCamera() {
uni.navigateTo({
url: '/pages/camera/camera?img=' + this.imgLink
})
},
getImage(type) {
uni.chooseImage({
sourceType: [type],
crop: {
quality: 80,
width: 300,
height: 350
}, // 图片上传前做裁剪
// sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
success: (res) => {
for (let i = 0; i < res.tempFilePaths.length; i++) {
uni.getImageInfo({
src: res.tempFilePaths[i],
success: async (image) => {
const res2 = await uploadFile(res.tempFilePaths[i])
this.imgLink = this.$imgUrl + res2.data.newFile
uni.redirectTo({
url: '/pages/camera/camera?img=' + this.imgLink
})
}
});
}
}
});
},
receiveRenderData(val){
this.progressLoading = val
},
// 接受rendjs的值
renderProgressNumber(val) {
this.progressNumber = val
}
},
};
</script>
<script module="threeArea" lang="renderjs">
import * as THREE from 'three'
import {
OrbitControls
} from 'three/examples/jsm/controls/OrbitControls.js'
// 引入stl加载器
import {
STLLoader
} from 'three/examples/jsm/loaders/STLLoader.js'
var renderer, scene, camera, controls;
export default {
data() {
return {
modelFileLink: null,
ownerVm: null,
};
},
mounted() {},
methods: {
receiveInfo(newValue, oldValue, ownerVm, vm) {
if (newValue) {
this.initThree(newValue.modelFile);
// this.createGridHelper();
this.createControls();
// this.loadLinesFromStorage(newValue.storedLines);
console.log('this.ownerVm222222:' ,ownerVm);
this.ownerVm = ownerVm
}
},
initThree(modelFile) {
this.progressLoading = false
let container = document.getElementById('container')
scene = new THREE.Scene()
scene.background = new THREE.Color(0xECECEE);
const loader = new STLLoader()
console.log('before.loading');
// 把模型导入STLLoader加载器中
// loader.load('http://192.168.10.121:5500/a.stl', geometry => {
loader.load(modelFile, geometry => {
console.log('loading');
//创建一个BufferGeometry函数
const geometry1 = new THREE.BufferGeometry();
// geometry.attributes.position.array这个是获取模型的坐标 第二个参数: 3是三个数为一个坐标就是一个顶点
geometry1.setAttribute('position', new THREE.BufferAttribute(geometry.attributes
.position.array, 3))
const material1 = new THREE.MeshLambertMaterial({
color: 0xDACFBC, //0x00ff00 0xff0000设置材质颜色为红色
transparent: true, //开启透明
opacity: 0.96, //设置透明度
});
geometry.center();
const mesh = new THREE.Mesh(geometry, material1);
mesh.position.set(0, 12, 0)
mesh.scale.set(.8, .8, .8)
// mesh.position.set.x = 5 * Math.PI; //模型摆正 用这个就不用上面的position
mesh.castShadow = true;
scene.add(mesh);
},
(progress) => {
let progressNumber = `${Math.trunc(progress.loaded / progress.total * 100)}%`
setTimeout(()=> {
// 给逻辑层传递值
this.ownerVm.callMethod('renderProgressNumber', progressNumber);
}, 100);
if(progress.loaded === progress.total) {
// 加载完成
setTimeout(()=> {
this.ownerVm.callMethod('receiveRenderData', true);
}, 100);
}
},
(err) => {
console.error('加载失败:', err);
});
camera = new THREE.PerspectiveCamera(65, container.clientWidth / container.clientHeight, 0.1, 100)
// this.camera.position.z = 0.3
camera.position.set(-50, 0, 50)
// 设置照相机的朝向
camera.lookAt(-50, -50, -50)
// const directionalLight = new Three.DirectionalLight(0xFFFFFF,3.0);
// directionalLight.position.set(80, 100, 50);
// this.scene.add(directionalLight);
var hemiLight = new THREE.HemisphereLight(0xDACFBC, 1) //0xFFFFFF
hemiLight.position.set(100, 100, 100)
scene.add(hemiLight)
renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setSize(container.clientWidth, container.clientHeight)
container.appendChild(renderer.domElement)
this.render();
},
createGridHelper() {
// 设置网格
const gridHelper = new THREE.GridHelper(50, 10);
scene.add(gridHelper);
},
createControls() {
controls = new OrbitControls(camera, renderer.domElement);
},
render() {
requestAnimationFrame(() => this.render());
renderer.render(scene, camera);
},
destroyThreeJSInstance() {
// 移除事件监听器
// object.removeEventListener('click', onClick);
// 清除渲染器和画布
renderer.dispose();
document.getElementById('container').removeChild(renderer.domElement);
// 删除场景中的所有对象
scene.traverse((object) => {
if (object.isMesh) {
object.geometry.dispose();
object.material.dispose();
}
});
// 重置相机和其他辅助对象
camera.position.set(0, 0, 0);
// 解除引用
scene = null;
camera = null;
renderer = null;
},
}
};
</script>
<style scoped lang="scss">
#container {
height: 100vh;
}
.detail_btn {
position: fixed;
bottom: 30rpx;
left: 30rpx;
right: 30rpx;
.detail_btns {
width: 630rpx;
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
border-radius: 60rpx;
background: #437DFF;
}
}
.popup_cont {
width: 653rpx;
height: 60vh;
border-radius: 8rpx;
display: flex;
justify-content: center;
align-items: center;
}
</style>