前言: 因?yàn)楣拘枨? 需要在App中內(nèi)嵌一個(gè)3D模型. 在市場(chǎng)上看了一下情況, 大部分都是vue2的, 并沒有vue3的版本...現(xiàn)在vue3也不是個(gè)新東西了. 后期模型會(huì)放入App內(nèi). 下面寫法并不支持App(已解決在App中渲染, 關(guān)注我可見), 支持h5
template:
<template>
<view class="">
<view id="threeView">456</view>
<view class="">
22222
</view>
</view>
</template>
js:
<script module="three" lang="renderjs" setup>
import * as THREE from 'three'
//引入軌道控制器(用來通過鼠標(biāo)事件控制模型旋轉(zhuǎn)、縮放、移動(dòng))
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'
import {
computed,
onMounted,
ref,
watch
} from 'vue'
// 如果模型沒有顯示出來, 可能是cameraZ的值不夠, 請(qǐng)注意
let scene = '',
camera = '',
renderer = '',
cube = '',
sphere = '',
step = '',
stats = '',
group = '',
cameraZ = 500,
url = '../../static/Eraser(1).glb',
width = 800,
height = 560,
orbitcontrols = '';
const init = () => {
console.log(cameraZ, 'cameraZ');
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
camera.position.set(0, 0, cameraZ);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xffffff, 0);
renderer.setSize(width / 1.2, height / 1.2);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMapEnabled = true;
document.getElementById("threeView").appendChild(renderer.domElement);
orbitcontrols = new OrbitControls(camera, renderer.domElement); //移動(dòng)控件
orbitcontrols.enabled = true;
orbitcontrols.enableRotate = true;
orbitcontrols.enableZoom = false;
orbitcontrols.autoRotate = true;
orbitcontrols.minPolarAngle = Math.PI / 4;
orbitcontrols.maxPolarAngle = 3 - (Math.PI / 4);
console.log('78', url.endsWith('gltf'), url.endsWith('glb'))
console.log(url)
if (url.endsWith('gltf') || url.endsWith('glb')) {
//設(shè)置了六個(gè)平行光 有些材質(zhì)不接受環(huán)境光會(huì)很暗
const directionLight1 = new THREE.DirectionalLight(0xffffff, 1);
directionLight1.position.set(-300, 0, 0)
scene.add(directionLight1);
const directionLight2 = new THREE.DirectionalLight(0xffffff, 1);
directionLight2.position.set(300, 0, 0)
scene.add(directionLight2);
const directionLight3 = new THREE.DirectionalLight(0xffffff, 1);
directionLight3.position.set(0, 300, 0)
scene.add(directionLight3);
const directionLight4 = new THREE.DirectionalLight(0xffffff, 1);
directionLight4.position.set(0, 300, 0)
scene.add(directionLight4);
const directionLight5 = new THREE.DirectionalLight(0xffffff, 1);
directionLight5.position.set(0, 0, -300)
scene.add(directionLight5);
const directionLight6 = new THREE.DirectionalLight(0xffffff, 1);
directionLight6.position.set(0, 0, 300)
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);
scene.add(Ambient);
scene.add(Sun);
}
const loadModel = () => {
let loader1 = new GLTFLoader();
let FBXloader = new FBXLoader();
let rotateObj = [];
const loadLoader = url.endsWith('fbx') ? FBXloader : loader1;
loadLoader.load(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(camera,'相機(jī)的信息',group,'組的信息');
let dist = Math.abs(camera.position.z - group.position.z - (mdwid / 2));
//console.log('dist值為:' + dist );
let vFov = 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 = height * fraction;
//console.log('finalHeight值為:' + finalHeight);
let finalWidth = (finalHeight * mdlen) / mdhei;
//console.log('finalWidth值為:' + finalWidth );
let value1 = width / finalWidth;
// console.log('value1縮放比例值為:' + value1);
let value2 = 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(); //去掉加載效果
scene.add(group);
// let boxhelper = new THREE.BoxHelper(group,0xbe1915); //輔助線外面紅色框
// scene.add(boxhelper);
})
}
const animate = () => {
requestAnimationFrame(animate);
orbitcontrols.update(); //自動(dòng)旋轉(zhuǎn)
renderer.render(scene, camera);
}
setTimeout(() => {
init();
animate();
loadModel();
}, 100)
</script>
上面寫法并不優(yōu)雅, 只是臨時(shí)作為一個(gè)demo可以參考.
注意: 需要自己手動(dòng)下載three, 在npm中npm i three即可, 同時(shí)注意script中的屬性
模型鏈接:百度網(wǎng)盤 請(qǐng)輸入提取碼文章來源:http://www.zghlxwxcb.cn/news/detail-531497.html
提取碼:?zsbn文章來源地址http://www.zghlxwxcb.cn/news/detail-531497.html
到了這里,關(guān)于uniapp vue3中使用threejs渲染3D模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!