赞
踩
前言: 因为公司需求, 需要在App中内嵌一个3D模型. 在市场上看了一下情况, 大部分都是vue2的, 并没有vue3的版本...现在vue3也不是个新东西了. 后期模型会放入App内. 下面写法并不支持App(已解决在App中渲染, 关注我可见), 支持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'
- //引入轨道控制器(用来通过鼠标事件控制模型旋转、缩放、移动)
- 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的值不够, 请注意
- 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); //移动控件
- 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')) {
- //设置了六个平行光 有些材质不接受环境光会很暗
- 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; //边界的最小坐标值 边界的最大坐标值
- 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,'相机的信息',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(); //自动旋转
- renderer.render(scene, camera);
- }
- setTimeout(() => {
- init();
- animate();
- loadModel();
- }, 100)
- </script>
上面写法并不优雅, 只是临时作为一个demo可以参考.
注意: 需要自己手动下载three, 在npm中npm i three即可, 同时注意script中的属性
模型链接:百度网盘 请输入提取码
提取码: zsbn
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。