uniapp vue3中引入外部3D模型(适配App)

您所在的位置:网站首页 uniapp3dtouch uniapp vue3中引入外部3D模型(适配App)

uniapp vue3中引入外部3D模型(适配App)

2024-07-06 02:28| 来源: 网络整理| 查看: 265

uniapp vue3中引入外部3D模型(适配App)

主要方式是通过renderjs来实现的, 因为使用threejs的话需要获取页面上的dom节点, 然后需要把threejs创建出来的canvans添加到页面的dom节点上. 就避免不了要获取dom了. 官网地址: https://uniapp.dcloud.net.cn/tutorial/renderjs.html#renderjs 很草率… 而且连例子都是vue2的. 放在vue3中肯定跑不起来, 例子也不是3D 下面例子使用的是网络地址, 使用前请确保项目安装了threejs, 只需npm i three即可.

{{ title }} import { onHide } from '@dcloudio/uni-app' import { ref, onDeactivated } from 'vue' const title = ref('Hello') const type = ref(0) const isHide = ref(false) const chanage = () => { console.log('隐藏') isHide.value = true } onHide(() => { isHide.value = true }) onDeactivated(() => { isHide.value = true }) setInterval(() => { // console.log('触发') type.value = Date.now() }, 1000) // @ts-nocheck import * as THREE from 'three' // OrbitControls 是对 Threejs 的三维场景进行缩放、平移、旋转操作 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' // 导入 glb 格式模型,若要导入其他格式模型,可尝试在 loaders 目录下加载其他文件 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js' var renderer; var scene; var camera; var controls; var ambient; export default { data() { return { ownerInstance: {} } }, methods: { handleAction(newValue, oldValue, ownerInstance, instance) { this.ownerInstance = ownerInstance if (newValue) { console.log(document.querySelector('canvas')) console.log(document.querySelector('#app')) document.querySelector('.threeId').removeChild(document.querySelector('.canvasId')) // document.querySelector('canvas').remove() } // console.log('newValue', newValue) // console.log('oldValue', oldValue) // console.log('该停止渲染了') }, leadModel() { let loader = new GLTFLoader(); // 导入本地或者服务器上的模型都可以 loader.load('https://dtmall-tel.alicdn.com/edgeComputingConfig/upload_models/1591673169101/RobotExpressive.glb', (gltf) => { scene.add(gltf.scene); }); }, animate() { requestAnimationFrame(this.animate); controls.update(); //自动旋转 // console.log('渲染', scene.value, camera) renderer.render(scene, camera); //执行渲染操作 }, initThree() { // 如果返回的不是未定义,说明threejs成功引入 // console.log('打印场景API', THREE.Scene); /* 创建场景对象Scene */ scene = new THREE.Scene(); // 环境光 ambient = new THREE.AmbientLight(0xffffff); scene.add(ambient); /* 相机设置 */ // var width = window.innerWidth; // 窗口宽度 // var height = window.innerHeight; // 高度 var width = 400; // 窗口宽度 var height = 300; // 高度 // 相机位置 var cameraZ = 10; // var k = width / height; // 窗口宽高比 var s = 400; // 三维场景显示范围控制系数,系数越大,显示的范围越大 // 创建相机对象(正射投影) camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000); camera.position.set(0, 0, cameraZ); //设置相机的摆放位置 camera.lookAt(new THREE.Vector3(0, 0, 0)); // 控制相机的焦点(镜头)位置,决定相机的朝向(取值为3维坐标对象-THREE.Vector3(x,y,z)) /* 创建渲染器对象 */ renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true //设置透明,为true时,背景颜色需要注释掉 }); renderer.setSize(width, height); // 设置渲染区域尺寸 // renderer.setClearColor(0XECF1F3, 1); // 设置背景颜色 // 改成vue去操作dom // console.log(threeViwe.value) // const element = document.getElementById('threeView') let div = document.createElement('uni-view') div.classList.add("threeId") renderer.domElement.style.position = 'absolute' renderer.domElement.style.left = '0' renderer.domElement.style.top = '500px' renderer.domElement.classList.add("canvasId") // renderer.domElement.style.display = 'none' div.appendChild(renderer.domElement) // console.log('查看App', document.querySelector('#app')) console.log(document.querySelector('.text-area')) document.querySelector('.text-area').appendChild(div) // 执行渲染操作,指定场景,相机作为参数 renderer.render(scene, camera); // 加载控件 controls = new OrbitControls(camera, renderer.domElement) controls.enabled = true; controls.enableRotate = true; controls.enableZoom = false; controls.autoRotate = true; controls.minPolarAngle = Math.PI / 4; controls.maxPolarAngle = 3 - (Math.PI / 4); } }, created() { setTimeout(() => { this.initThree(); //加载场景 this.leadModel(); //导入模型 this.animate(); //动画 }) } }

就是这样了, 然后离开页面的时候销毁这个canvas, 下次进来再创建. 注意下面不能用setup来整, 下面要用vue2的写法来就可以了, 用vue3的setup会出现拿不到dom的情况 注意server层和renderjs层之间的通讯

.content { display: flex; flex-direction: column; align-items: center; justify-content: center; } .logo { height: 200rpx; width: 200rpx; margin-top: 200rpx; margin-left: auto; margin-right: auto; margin-bottom: 50rpx; } .text-area { display: flex; justify-content: center; } .title { font-size: 36rpx; color: #8f8f94; }

注意在浏览器和App中是不一样的

如果相加样式的话, 直接在添加节点到dom前设置即可 如下:

在这里插入图片描述 才发现可以这样玩 不过现在一般在网页内嵌3D时, 都会给一个压缩的版本, 所以需要解压. 解压依赖于DRACOLoader

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3