当前位置:   article > 正文

uniapp vue3中使用threejs渲染3D模型_uniapp threejs

uniapp threejs

前言: 因为公司需求, 需要在App中内嵌一个3D模型. 在市场上看了一下情况, 大部分都是vue2的, 并没有vue3的版本...现在vue3也不是个新东西了. 后期模型会放入App内. 下面写法并不支持App(已解决在App中渲染, 关注我可见), 支持h5

template:

  1. <template>
  2. <view class="">
  3. <view id="threeView">456</view>
  4. <view class="">
  5. 22222
  6. </view>
  7. </view>
  8. </template>

js:

  1. <script module="three" lang="renderjs" setup>
  2. import * as THREE from 'three'
  3. //引入轨道控制器(用来通过鼠标事件控制模型旋转、缩放、移动)
  4. import {
  5. OrbitControls
  6. } from 'three/examples/jsm/controls/OrbitControls.js'
  7. import {
  8. GLTFLoader
  9. } from 'three/examples/jsm/loaders/GLTFLoader.js'
  10. import {
  11. FBXLoader
  12. } from 'three/examples/jsm/loaders/FBXLoader.js'
  13. import {
  14. computed,
  15. onMounted,
  16. ref,
  17. watch
  18. } from 'vue'
  19. // 如果模型没有显示出来, 可能是cameraZ的值不够, 请注意
  20. let scene = '',
  21. camera = '',
  22. renderer = '',
  23. cube = '',
  24. sphere = '',
  25. step = '',
  26. stats = '',
  27. group = '',
  28. cameraZ = 500,
  29. url = '../../static/Eraser(1).glb',
  30. width = 800,
  31. height = 560,
  32. orbitcontrols = '';
  33. const init = () => {
  34. console.log(cameraZ, 'cameraZ');
  35. scene = new THREE.Scene();
  36. camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
  37. camera.position.set(0, 0, cameraZ);
  38. renderer = new THREE.WebGLRenderer({
  39. antialias: true
  40. });
  41. renderer.setClearColor(0xffffff, 0);
  42. renderer.setSize(width / 1.2, height / 1.2);
  43. renderer.setPixelRatio(window.devicePixelRatio);
  44. renderer.shadowMapEnabled = true;
  45. document.getElementById("threeView").appendChild(renderer.domElement);
  46. orbitcontrols = new OrbitControls(camera, renderer.domElement); //移动控件
  47. orbitcontrols.enabled = true;
  48. orbitcontrols.enableRotate = true;
  49. orbitcontrols.enableZoom = false;
  50. orbitcontrols.autoRotate = true;
  51. orbitcontrols.minPolarAngle = Math.PI / 4;
  52. orbitcontrols.maxPolarAngle = 3 - (Math.PI / 4);
  53. console.log('78', url.endsWith('gltf'), url.endsWith('glb'))
  54. console.log(url)
  55. if (url.endsWith('gltf') || url.endsWith('glb')) {
  56. //设置了六个平行光 有些材质不接受环境光会很暗
  57. const directionLight1 = new THREE.DirectionalLight(0xffffff, 1);
  58. directionLight1.position.set(-300, 0, 0)
  59. scene.add(directionLight1);
  60. const directionLight2 = new THREE.DirectionalLight(0xffffff, 1);
  61. directionLight2.position.set(300, 0, 0)
  62. scene.add(directionLight2);
  63. const directionLight3 = new THREE.DirectionalLight(0xffffff, 1);
  64. directionLight3.position.set(0, 300, 0)
  65. scene.add(directionLight3);
  66. const directionLight4 = new THREE.DirectionalLight(0xffffff, 1);
  67. directionLight4.position.set(0, 300, 0)
  68. scene.add(directionLight4);
  69. const directionLight5 = new THREE.DirectionalLight(0xffffff, 1);
  70. directionLight5.position.set(0, 0, -300)
  71. scene.add(directionLight5);
  72. const directionLight6 = new THREE.DirectionalLight(0xffffff, 1);
  73. directionLight6.position.set(0, 0, 300)
  74. scene.add(directionLight6);
  75. }
  76. let Sun = new THREE.DirectionalLight(0xffffff, 1);
  77. Sun.position.set(0, 300, 0);
  78. Sun.castShadow = true;
  79. let Ambient = new THREE.AmbientLight(0xffffff, 1);
  80. scene.add(Ambient);
  81. scene.add(Sun);
  82. }
  83. const loadModel = () => {
  84. let loader1 = new GLTFLoader();
  85. let FBXloader = new FBXLoader();
  86. let rotateObj = [];
  87. const loadLoader = url.endsWith('fbx') ? FBXloader : loader1;
  88. loadLoader.load(url, function(gltf) {
  89. const loadscene = gltf.scene || gltf;
  90. loadscene.scale.set(1, 1, 1);
  91. let group = new THREE.Group();
  92. group.add(loadscene);
  93. let bbox = new THREE.Box3().setFromObject(group);
  94. // console.log(bbox,'bbox---');
  95. let mdlen = bbox.max.x - bbox.min.x; //边界的最小坐标值 边界的最大坐标值
  96. let mdhei = bbox.max.y - bbox.min.y;
  97. let mdwid = bbox.max.z - bbox.min.z;
  98. group.position.set(0, 0, 0);
  99. // console.log(camera,'相机的信息',group,'组的信息');
  100. let dist = Math.abs(camera.position.z - group.position.z - (mdwid / 2));
  101. //console.log('dist值为:' + dist );
  102. let vFov = camera.fov * Math.PI / 180; //弧度=角度*Math.PI/180
  103. //console.log('vFov值为:' + vFov );
  104. let vheight = 2 * Math.tan(vFov * 0.5) * dist;
  105. //console.log('vheight值为:' + vheight );
  106. let fraction = mdhei / vheight;
  107. // console.log('fraction值为:' + fraction );
  108. let finalHeight = height * fraction;
  109. //console.log('finalHeight值为:' + finalHeight);
  110. let finalWidth = (finalHeight * mdlen) / mdhei;
  111. //console.log('finalWidth值为:' + finalWidth );
  112. let value1 = width / finalWidth;
  113. // console.log('value1缩放比例值为:' + value1);
  114. let value2 = height / finalHeight;
  115. // console.log('value2缩放比例值为:' + value2);
  116. if (value1 >= value2) {
  117. group.scale.set(value2, value2, value2);
  118. } else {
  119. group.scale.set(value1 / 2, value1 / 2, value1 / 2);
  120. // group.scale.set(value1,value1,value1);
  121. }
  122. let bbox2 = new THREE.Box3().setFromObject(group)
  123. // console.log(bbox2,'bbox2');
  124. let mdlen2 = bbox2.max.x - bbox2.min.x;
  125. let mdhei2 = bbox2.max.y - bbox2.min.y;
  126. let mdwid2 = bbox2.max.z - bbox2.min.z;
  127. group.position.set(-(bbox2.max.x + bbox2.min.x) / 2,
  128. -(bbox2.max.y + bbox2.min.y) / 2,
  129. -(bbox2.max.z + bbox2.min.z) / 2);
  130. document.getElementById("threeView").click(); //去掉加载效果
  131. scene.add(group);
  132. // let boxhelper = new THREE.BoxHelper(group,0xbe1915); //辅助线外面红色框
  133. // scene.add(boxhelper);
  134. })
  135. }
  136. const animate = () => {
  137. requestAnimationFrame(animate);
  138. orbitcontrols.update(); //自动旋转
  139. renderer.render(scene, camera);
  140. }
  141. setTimeout(() => {
  142. init();
  143. animate();
  144. loadModel();
  145. }, 100)
  146. </script>

上面写法并不优雅, 只是临时作为一个demo可以参考.

注意: 需要自己手动下载three, 在npm中npm i three即可, 同时注意script中的属性

模型链接:百度网盘 请输入提取码

提取码: zsbn

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/123953
推荐阅读
相关标签
  

闽ICP备14008679号