组件模板
- n-text-loading是我的自定义loading组件,可以自行替换
- id是threeView是模型显示的位置,
- props里面的url是模型链接,cameraZ是相机位置,默认100,一般不需要改,有些z轴很长的模型旋转的时候会有一部分相机看不到这个时候就需要调整这个值了,这两个要从后台上传。
- :prop=“url”,url就是你传给renderjs的值,不传的话renderjs中拿不到,
- :change:prop=“thress.updataModelUrl”,这个表示prop改变了会执行模块thress中的updataModelUrl方法,这个方法接收四个参数newValue, oldValue, ownerInstance, instance
<template>
<view class="collection-bg">
<n-text-loading v-if="loading"></n-text-loading>
<view id="threeView"
@click="thress.onClick"
:prop="url"
:change:prop="thress.updataModelUrl"
:propz="cameraZ"
:change:propz="thress.updataModelZ"
class="media-wrap"
></view>
</view>
</template>
<script>
export default{
props:{
url: String,
cameraZ: Number
},
data(){
return{
loading: true,
}
},
methods:{
completed(option){
this.loading = option.loading || false;
}
}
}
</script>
renderjs
- script里面的module="thress"和上面template里面的thress是对应的,别写错了
- three自己npm下载就可以了
- template里面是用不了renderjs中的data的值的,所以控制加载中的属性loading我是放在上面的,加载完成之后调用id为threeView的点击事件,然后会执行renderjs中onClick方法,onClick会收到两个参数event, ownerInstance,再使用ownerInstance.callMethod()方法,可以传两个参数,第一个是上面方法名,第二个是你要传递的参数,比如这样: ownerInstance.callMethod(‘completed’, { loading: false });
- 好像也没啥了,其他直接复制就OK了。
<script module="thress" lang="renderjs">
// import THREE from 'three/build/three.min.js'
const THREE = require('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 {
name:"ModelScale",
data(){
return{
scene:null,
camera:null,
renderer:null,
cube:null,
sphere:null,
step:0,
stats:null,
group:null,
orbitcontrols: null,
}
},
props:{
width:{type:Number,default: 375},
height:{type:Number,default: 380},
},
methods:{
updataModelUrl(newValue, oldValue, ownerInstance, instance) {
// 监听 service 层数据变更
console.log(newValue,'层数据变更');
},
updataModelZ(newValue, oldValue, ownerInstance, instance){
console.log(newValue,'层数据变更2');
},
onClick(event, ownerInstance){
ownerInstance.callMethod('completed', {
loading: false
})
},
init(){
const cameraZ = this.cameraZ <= 0 ? 100 : this.cameraZ;
console.log(cameraZ,'cameraZ');
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(45,this.width/this.height,0.1,1000);
this.camera.position.set(0,0,cameraZ);
this.renderer = new THREE.WebGLRenderer({antialias: true });
this.renderer.setClearColor(0xffffff,0);
this.renderer.setSize(this.width/1.2,this.height/1.2);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.shadowMapEnabled = true;
document.getElementById("threeView").appendChild(this.renderer.domElement);
this.orbitcontrols = new OrbitControls(this.camera, this.renderer.domElement); //移动控件
this.orbitcontrols.enabled = true;
this.orbitcontrols.enableRotate =true;
this.orbitcontrols.enableZoom = false;
this.orbitcontrols.autoRotate = true;
this.orbitcontrols.minPolarAngle = Math.PI / 4;
this.orbitcontrols.maxPolarAngle = 3 - (Math.PI / 4);
// let axes = new THREE.AxesHelper(100);//辅助线
// this.scene.add(axes);
if(this.url.endsWith('gltf') || this.url.endsWith('glb')){
//设置了六个平行光 有些材质不接受环境光会很暗
const directionLight1 = new THREE.DirectionalLight(0xffffff, 1);
directionLight1.position.set(-300,0,0)
this.scene.add(directionLight1);
const directionLight2 = new THREE.DirectionalLight(0xffffff, 1);
directionLight2.position.set(300,0,0)
this.scene.add(directionLight2);
const directionLight3 = new THREE.DirectionalLight(0xffffff, 1);
directionLight3.position.set(0,300,0)
this.scene.add(directionLight3);
const directionLight4 = new THREE.DirectionalLight(0xffffff, 1);
directionLight4.position.set(0,300,0)
this.scene.add(directionLight4);
const directionLight5 = new THREE.DirectionalLight(0xffffff, 1);
directionLight5.position.set(0,0,-300)
this.scene.add(directionLight5);
const directionLight6 = new THREE.DirectionalLight(0xffffff, 1);
directionLight6.position.set(0,0,300)
this.scene.add(directionLight6);
}
let Sun = new THREE.DirectionalLight(0xffffff, 1);
Sun.position.set(0,300,0);
Sun.castShadow = true;
let Ambient = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(Ambient);
this.scene.add(Sun);
},
loadModel(){
let self = this; //这一点很重要。。
let loader1 = new GLTFLoader();
let FBXloader = new FBXLoader();
let rotateObj = [];
const loadLoader = this.url.endsWith('fbx') ? FBXloader : loader1;
loadLoader.load(this.url,function (gltf){
const loadscene = gltf.scene || gltf;
loadscene.scale.set(1,1,1);
let group = new THREE.Group();
group.add(loadscene);
let bbox = new THREE.Box3().setFromObject(group);
// console.log(bbox,'bbox---');
let mdlen=bbox.max.x-bbox.min.x; //边界的最小坐标值 边界的最大坐标值
let mdhei=bbox.max.y-bbox.min.y;
let mdwid=bbox.max.z-bbox.min.z;
group.position.set(0,0,0);
// console.log(self.camera,'相机的信息',group,'组的信息');
let dist =Math.abs(self.camera.position.z - group.position.z- (mdwid/2));
//console.log('dist值为:' + dist );
let vFov = self.camera.fov * Math.PI/180; //弧度=角度*Math.PI/180
//console.log('vFov值为:' + vFov );
let vheight = 2 * Math.tan(vFov * 0.5) *dist;
//console.log('vheight值为:' + vheight );
let fraction = mdhei / vheight;
// console.log('fraction值为:' + fraction );
let finalHeight = self.height * fraction ;
//console.log('finalHeight值为:' + finalHeight);
let finalWidth = (finalHeight*mdlen) /mdhei;
//console.log('finalWidth值为:' + finalWidth );
let value1 = self.width/finalWidth;
// console.log('value1缩放比例值为:' + value1);
let value2 = self.height/finalHeight;
// console.log('value2缩放比例值为:' + value2);
if(value1 >= value2){
group.scale.set(value2,value2,value2);
}
else{
group.scale.set(value1 /2,value1/2,value1/2);
// group.scale.set(value1,value1,value1);
}
let bbox2= new THREE.Box3().setFromObject(group)
// console.log(bbox2,'bbox2');
let mdlen2=bbox2.max.x-bbox2.min.x;
let mdhei2=bbox2.max.y-bbox2.min.y;
let mdwid2=bbox2.max.z-bbox2.min.z;
group.position.set(-(bbox2.max.x+bbox2.min.x)/2,
-(bbox2.max.y+bbox2.min.y)/2,
-(bbox2.max.z+bbox2.min.z)/2);
document.getElementById("threeView").click(); //去掉加载效果
self.scene.add(group);
// let boxhelper = new THREE.BoxHelper(group,0xbe1915); //辅助线外面红色框
// self.scene.add(boxhelper);
});
},
animate(){
requestAnimationFrame(this.animate);
this.orbitcontrols.update(); //自动旋转
this.renderer.render(this.scene,this.camera);
}
},
mounted(){
window.ob = this;
this.init();
this.animate();
this.loadModel();
}
}
</script>
文章来源地址https://www.toymoban.com/news/detail-628422.html
文章来源:https://www.toymoban.com/news/detail-628422.html
到了这里,关于uniapp通过renderjs加载3D模型,支持FBX、GLB和GLTF模型,模型可自动适应。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!