組件模板
- n-text-loading是我的自定義loading組件,可以自行替換
- id是threeView是模型顯示的位置,
- props里面的url是模型鏈接,cameraZ是相機(jī)位置,默認(rèn)100,一般不需要改,有些z軸很長(zhǎng)的模型旋轉(zhuǎn)的時(shí)候會(huì)有一部分相機(jī)看不到這個(gè)時(shí)候就需要調(diào)整這個(gè)值了,這兩個(gè)要從后臺(tái)上傳。
- :prop=“url”,url就是你傳給renderjs的值,不傳的話renderjs中拿不到,
- :change:prop=“thress.updataModelUrl”,這個(gè)表示prop改變了會(huì)執(zhí)行模塊thress中的updataModelUrl方法,這個(gè)方法接收四個(gè)參數(shù)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是對(duì)應(yīng)的,別寫錯(cuò)了
- three自己npm下載就可以了
- template里面是用不了renderjs中的data的值的,所以控制加載中的屬性loading我是放在上面的,加載完成之后調(diào)用id為threeView的點(diǎn)擊事件,然后會(huì)執(zhí)行renderjs中onClick方法,onClick會(huì)收到兩個(gè)參數(shù)event, ownerInstance,再使用ownerInstance.callMethod()方法,可以傳兩個(gè)參數(shù),第一個(gè)是上面方法名,第二個(gè)是你要傳遞的參數(shù),比如這樣: ownerInstance.callMethod(‘completed’, { loading: false });
- 好像也沒(méi)啥了,其他直接復(fù)制就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) {
// 監(jiān)聽 service 層數(shù)據(jù)變更
console.log(newValue,'層數(shù)據(jù)變更');
},
updataModelZ(newValue, oldValue, ownerInstance, instance){
console.log(newValue,'層數(shù)據(jù)變更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); //移動(dòng)控件
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')){
//設(shè)置了六個(gè)平行光 有些材質(zhì)不接受環(huán)境光會(huì)很暗
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; //這一點(diǎn)很重要。。
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; //邊界的最小坐標(biāo)值 邊界的最大坐標(biāo)值
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,'相機(jī)的信息',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(); //自動(dòng)旋轉(zhuǎn)
this.renderer.render(this.scene,this.camera);
}
},
mounted(){
window.ob = this;
this.init();
this.animate();
this.loadModel();
}
}
</script>
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-628422.html
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-628422.html
到了這里,關(guān)于uniapp通過(guò)renderjs加載3D模型,支持FBX、GLB和GLTF模型,模型可自動(dòng)適應(yīng)。的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!