• Threejs 加载模型、旋转、弹框操作


    参考文档

    Three.js电子书《Three.js零基础入门教程》_郭隆邦

    Three.js – JavaScript 3D Library

    Three.js之灯光_disasters的博客-CSDN博客_threejs 灯光

    『Three.js』辅助坐标轴_德育处主任Pro的博客-CSDN博客

    Three.js学习笔记-OrbitControls.js让摄像机围绕目标旋转_fewbadboy的博客-CSDN博客_orbitcontrols 旋转

    dom-to-image - npm

    安装three.js

    npm install three -d

    引入three.js并加载所需插件

    1. import * as THREE from 'three';
    2. import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
    3. import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
    4. import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

    three.js的三大基本要素

    渲染器

    1. renderer = new THREE.WebGLRenderer(); //实例化渲染器
    2. renderer.setSize(window.innerWidth, window.innerHeight); //设置宽和高
    3. document.body.appendChild(renderer.domElement); // 添加到dom

    场景

    scene = new THREE.Scene(); // 实例化场景

    相机

    1. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000000); //实例化相机
    2. camera.position.set(200, 100, 100); //相机的位置
    3. camera.lookAt(new THREE.Vector3(0, 0, 0));//相机看向的位置

    到这里打开浏览器应该会发现一个黑色的canvas标签。

    requestAnimationFrame

    1. animate() { // 很多操作都要在这里更新才能有效果
    2. requestAnimationFrame(this.animate);
    3. },

    加载模型,播放动画

    1. const loader = new GLTFLoader();
    2. // 有的模型需要解压才能加载
    3. const dracoLoader = new DRACOLoader();
    4. dracoLoader.setDecoderPath('/draco/');
    5. loader.setDRACOLoader(dracoLoader);
    6. loader.load('文件路径', (gltf) => {
    7. //将模型添加至场景
    8. scene.add(gltf.scene) // 根据访问的文件类型不同,可能需要.scene,也可能直接访问gltf,自己尝试一下就好了
    9. //直接添加模型后会把模型的一个角对准坐标轴的原点,获取模型的大小除2计算后设置位置,让坐标轴原点刚好在模型的正中心,方便后续操作
    10. var box = new THREE.Box3().setFromObject(gltf.scene);
    11. gltf.scene.position.set(mean(box.max.x, box.min.x), mean(box.max.y, box.min.y), mean(box.max.z, box.min.z));
    12. function mean(v1, v2) {
    13. return -(Math.abs(v1 - v2) / 2);
    14. }
    15. // 播放模型的动画,一个模型中可携带多个动画
    16. mixer = new THREE.AnimationMixer(gltf.scene);// 初始化混合器,这里的传参参考scene.add
    17. var AnimationAction = mixer.clipAction(gltf.animations[0]); // 传入一个动画
    18. AnimationAction.play(); // 播放
    19. })

    DRACOLoader加载器有的模型需要,有的不需要。页面报

     这个错误时就需要加上。

    OrbitControls控制器

    可以通过鼠标或者滚轮放大缩小移动模型。

    1. controls = new OrbitControls(camera, renderer.domElement); // 初始化
    2. controls.maxPolarAngle = Math.PI / 2; // 设置垂直旋转的最大角度
    3. controls.minPolarAngle = 0; // 设置垂直旋转的最小角度
    4. // 这两个设置目前达到的效果是不能看模型的底面
    5. controls.autoRotate = true; // 镜头自动旋转

    灯光

    在没有添加灯光是会有一个默认的灯光使我们也能看到模型,在我们添加灯光后消失。

    1. scene.add(new THREE.AmbientLight(0xffffff)); // 白色的全局光,使模型不是那么黑白分明
    2. var directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 初始化平行光,模拟太阳
    3. directionalLight.position.set(100, 104, 200); // 设置位置
    4. scene.add(directionalLight); // 添加到场景

    点击模型弹出文字信息

    安装dom-to-image并引入

    1. npm install dom-to-image
    2. import domtoimage from 'dom-to-image';
    1. //获取鼠标坐标 处理点击某个模型的事件
    2. let mouse = new THREE.Vector2(); // 初始化一个2D坐标用于存储鼠标位置
    3. let raycaster = new THREE.Raycaster(); // 初始化光线追踪
    4. function onmodelclick(event) {
    5. // 获取鼠标点击位置
    6. mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    7. mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    8. raycaster.setFromCamera(mouse, camera);
    9. const intersects = raycaster.intersectObjects(scene.children); // 获取点击到的模型的数组,从近到远排列
    10. console.log(intersects);
    11. var worldPosition = new THREE.Vector3(); // 初始化一个3D坐标,用来记录模型的世界坐标
    12. if (intersects.length) {
    13. intersects[0].object.getWorldPosition(worldPosition); // 将点中的3D模型坐标记录到worldPosition中
    14. // 将dom节点转换为base64编码的图片
    15. domtoimage.toPng(document.getElementById("节点ID"))
    16. .then((dataUrl) => {
    17. var texture = new THREE.TextureLoader().load(dataUrl);
    18. var spriteMaterial = new THREE.SpriteMaterial({
    19. map: texture,//设置精灵纹理贴图
    20. });
    21. sprite = new THREE.Sprite(spriteMaterial); // 精灵模型,不管从哪个角度看都可以一直面对你
    22. scene.add(sprite);
    23. sprite.position.set(worldPosition.x, worldPosition.y + 3, worldPosition.z); // 根据刚才获取的世界坐标设置精灵模型位置,高度加了3,是为了使精灵模型显示在点击模型的上方
    24. })
    25. .catch(function (error) {
    26. console.error('oops, something went wrong!', error);
    27. });
    28. }
    29. }
    30. window.addEventListener("click", onmodelclick); // 监听点击事件

    辅助工具

    坐标轴

    1. var axes = new THREE.AxesHelper(20);
    2. scene.add(axes);

    平行光位置

    1. const helper = new THREE.DirectionalLightHelper(directionalLight, 5);
    2. scene.add(helper);

  • 相关阅读:
    2.Android系统启动
    设计模式-13-职责链(责任链)模式
    python代码规范PEP 8——常见的规范错误与解决办法
    21-CSS中的3D属性
    算法通关村之字符串(实战训练)经典问题:转换小写字母、字符串反转、K个一组反转、仅反转字母
    C++ 多态语法点
    MySQL 之 InnoDB存储引擎(一)
    .NET科普:.NET简史、.NET Standard以及C#和.NET Framework之间的关系
    uni-app:showModal中实现弹窗中文本框输入
    算法题:买卖股票的最佳时机 II (贪心算法解决股票问题)
  • 原文地址:https://blog.csdn.net/qq_18676843/article/details/124299912