shayloyuki

科技是第一生产力

 

安装/引入 three.js

方式一:cdn 引入

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
<script>
  var scene = new THREE.Scene()
  console.log(scene)
</script>

缺点:引入 three.js 的插件比如 OrbitControls 的 cdn(来源:https://www.cdnpkg.com/three-orbitcontrols) 后,会报错 Uncaught ReferenceError: require is not defined at OrbitControls.js:1:48

原因是 OrbitControls 的 cdn 中引入了 three,但实际上找不到安装的 three,因为这里 three 是通过 cdn 引入的。
目前还没找到解决办法,如果有小伙伴知道了,请在评论区告诉我~

image

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
<script src="https://unpkg.com/three-orbitcontrols@2.110.3/OrbitControls.js"></script>
<script>
  var scene = new THREE.Scene()
  console.log(scene)
</script>

方式二:用本地静态服务 Live Server 打开 htm

注意事项:

一定要用服务器打开,推荐使用插件 Live Server,否则直接把 html 在浏览器打开,会报错,提示跨域:

image


npm i three 后,新建 index.html,书写下述代码:

办法1(推荐):type="importmap"配置

<!-- 映射目录,即把 `three/addons/` 映射到 `../projects/node_modules/three/examples/jsm/`,注意一定两个地址的末尾都要加 `/`,否则会报错: `Uncaught TypeError: Failed to resolve module specifier "three/addons/controls/OrbitControls.js". Relative references must start with either "/", "./", or "../".` -->
<script type="importmap">
	{
		"imports": {
			"three": "../projects/node_modules/three/build/three.module.js",
        		"three/addons/": "../projects/node_modules/three/examples/jsm/"
		}
	}
</script>

<!-- script 标签中一定要加 `type="module"`,否则报错`Uncaught SyntaxError: Cannot use import statement outside a module` -->
<script type="module">
	import * as THREE from 'three';
	console.log('scene:', THREE.Scene);

	import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
	console.log(OrbitControls);

	import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
	console.log(GLTFLoader);

	// 注意版本变化:`three ^0.150.1` 最新版本

	// 旧版本的 THREE.SceneUtils.createMultiMaterialObject 更改为:
	import { createMultiMaterialObject } from 'three/addons/utils/SceneUtils.js'
	// 使用时直接用 createMultiMaterialObject

	// 旧版本的 `new THREE.AxisHelper` 更改为 `new THREE.AxesHelper`
</script>

办法2:ES6 import方式引入three.module.js

  <script type="module">
	// 报错:Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
    // import * as THREE from 'three';

	// 报错: `GET http://127.0.0.1:5500/three net::ERR_ABORTED 404 (Not Found)`
	// import * as THREE from '/three';

	// 正确:
	import * as THREE from './node_modules/three/build/three.module.js';
	var scene = new THREE.Scene()
	console.log(scene)
  </script>

办法3:script标签方式引入three.js

  <script src="./node_modules/three/build/three.js"></script>
  <script>
    // import * as THREE from './node_modules/three/build/three.module.js';
    var scene = new THREE.Scene()
    console.log(scene)
  </script>

方式三:用 vue/react 技术栈

<!-- threeTest.vue -->
<template>
  <div class="3d">3d</div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

export default {
  name: "ThreeDIndex",
  created() {
    console.log(THREE.Scene);
    console.log(OrbitControls);
    console.log(GLTFLoader);
  },
};
</script>

<style lang="scss" scoped></style>
一个 vue+three.js 的 demo
<template>
  <div class="3d"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import Stats from "three/examples/jsm/libs/stats.module";
import { createMultiMaterialObject } from "three/examples/jsm/utils/SceneUtils.js";
import * as dat from "dat-gui";
export default {
  name: "ThreeDIndex",
  created() {
    this.loadThreeD();
  },
  methods: {
    loadThreeD() {
      var scene = new THREE.Scene();

      var camera = new THREE.PerspectiveCamera(
        50,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.set(5, 10, 10);

      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      /* 1. 使用 dat.GUI 插件 */
      // 1.1 dat.GUI 定义对象,设置需要修改的数据
      var controls = {
        positionX: 0,
        positionY: 0,
        positionZ: 0,
      };

      /* 3. 使用 OrbitControls 插件 */
      // 3.1 实例化相机插件对象
      var control = new OrbitControls(camera, renderer.domElement);

      var geometry = new THREE.BoxGeometry(4, 4, 4);
      var materialBasic = new THREE.MeshBasicMaterial({
        color: 0xffffff,
        wireframe: true,
      });
      var materialNormal = new THREE.MeshNormalMaterial();

      var cube = createMultiMaterialObject(geometry, [
        materialBasic,
        materialNormal,
      ]);

      camera.lookAt(cube.position);

      scene.add(cube);

      var spotlight = new THREE.SpotLight(0xffffff);
      spotlight.position.set(0, 20, 20);
      spotlight.intensity = 5;
      scene.add(spotlight);

      var axes = new THREE.AxesHelper(6);
      scene.add(axes);

      /* 2. 使用 stats.js */
      // 2.1 实例化性能监视插件
      var stats = new Stats();
      // 2.2 把 stats 对象生成的 dom, 添加到页面中
      document.body.appendChild(stats.dom);

      function animate() {
        requestAnimationFrame(animate);

        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;

        // 2.3 更新性能插件
        stats.update();

        // 3.2 在每一帧执行update(可以实时更新一下网格的位置,这样效果更好)
        cube.position.set(2, 5, -6);
        // 更新相机插件
        control.update();

        renderer.render(scene, camera);
      }
      animate();

      // 1.2 实例化dat.GUI对象
      var gui = new dat.GUI();
      // 1.3 把需要修改的配置添加dat.GUI对象中
      gui.add(controls, "positionX", -10, 10).onChange(updatePosition);
      gui.add(controls, "positionY", -10, 10).onChange(updatePosition);
      gui.add(controls, "positionZ", -1, 1).onChange(updatePosition);
      // 1.4 定义更新模型位置函数
      function updatePosition() {
        cube.position.set(
          controls.positionX,
          controls.positionY,
          controls.positionZ
        );
      }
    },
  },
};
</script>

<style lang="scss" scoped></style>

参考链接

  1. 网上关于 three.js 的帖子不够精细,推荐一个学习 three.js 的网址:http://webgl3d.cn/pages/cd35b2/
  2. THREE.js 学习的时候,用的版本一定要注意

posted on 2023-03-09 14:14  shayloyuki  阅读(3123)  评论(0编辑  收藏  举报

导航