1、安装
"three": "^0.155.0", //主体 主要是这个
"three-obj-mtl-loader": "^1.0.3", // 加载外部模型
"dat-gui": "^0.5.0",//gui 设置
"@tweenjs/tween.js": "^21.0.0", //动画
2、官网
https://threejs.org/manual/#zh/textures
3、引入使用
import * as THREE from "three";
4、简单例子
1.太阳-地球-月亮
模拟场景与场景之间的联系
<html>
<head>
<meta charset="utf-8" />
<title>太阳系 three.js app</title>
<style>
html,
body {
margin: 0;
height: auto;
overflow-y: auto;
}
#c {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui"></div>
<script
async
src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"
></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.155.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.155.0/examples/jsm/"
}
}
</script>
<script type="module">
//导入
import * as THREE from "three";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
// function resizeRendererToDisplaySize(renderer) {
// const canvas = renderer.domElement;
// const width = canvas.clientWidth;
// const height = canvas.clientHeight;
// const needResize = canvas.width !== width || canvas.height !== height;
// if (needResize) {
// renderer.setSize(width, height, false);
// }
// return needResize;
// }
// 响应式处理
function resizeRendererToDisplaySize(renderer) {
// const canvas = renderer.domElement;
const canvas = document.querySelector("#c");
const pixelRatio = window.devicePixelRatio;
const width = (canvas.clientWidth * pixelRatio) | 0;
const height = (canvas.clientHeight * pixelRatio) | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function main() {
const canvas = document.querySelector("#c");
//创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
const gui = new GUI();
// 创建相机
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 50, 0);
camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);
// 创建场景
const scene = new THREE.Scene();
// 创建灯光
{
const color = 0xffffff;
const intensity = 500;
const light = new THREE.PointLight(color, intensity);
scene.add(light);
}
// 要更新旋转角度的对象数组
const objects = [];
// 创建场景图
const solarSystem = new THREE.Object3D();
scene.add(solarSystem);
objects.push(solarSystem);
// 创建地球场景
const earthOrbit = new THREE.Object3D();
earthOrbit.position.x = 10;
// scene.add(earthOrbit);
solarSystem.add(earthOrbit);
objects.push(earthOrbit);
// 创建月球场景
const moonOrbit = new THREE.Object3D();
moonOrbit.position.x = 2;
// scene.add(moonOrbit);
earthOrbit.add(moonOrbit);
objects.push(moonOrbit);
// 一球多用
const radius = 1;
const widthSegments = 6;
const heightSegments = 6;
const sphereGeometry = new THREE.SphereGeometry(
radius,
widthSegments,
heightSegments
);
// 地球
// const textGeometry = new THREE.TextGeometry(text, {
// font: font,
// size: size,
// height: height,
// curveSegments: curveSegments,
// bevelEnabled: bevelEnabled,
// bevelThickness: bevelThickness,
// bevelSize: bevelSize,
// });
// const textMesh = new THREE.Mesh(
// textGeometry,
// new THREE.MeshPhongMaterial({
// side: THREE.DoubleSide,
// emissive: 0xffff00,
// })
// );
// scene.add(textMesh);
{
// 创建一个太阳
const sunMaterial = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
emissive: 0xffff00,
});
const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
sunMesh.scale.set(5, 5, 5); // 扩大太阳的大小
// scene.add(sunMesh);
solarSystem.add(sunMesh);
objects.push(sunMesh);
// 创建地球
const earthMaterial = new THREE.MeshPhongMaterial({
color: 0x2233ff,
emissive: 0x112244,
});
const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial);
// earthMesh.position.x = 10;
// scene.add(earthMesh);
// 将地球变为太阳的子节点
// sunMesh.add(earthMesh);
earthOrbit.add(earthMesh);
objects.push(earthMesh);
// 创建月球
const moonMaterial = new THREE.MeshPhongMaterial({
color: 0x888888,
emissive: 0x222222,
});
const moonMesh = new THREE.Mesh(sphereGeometry, moonMaterial);
moonMesh.scale.set(0.5, 0.5, 0.5);
moonOrbit.add(moonMesh);
objects.push(moonMesh);
class AxisGridHelper {
constructor(node, units = 10) {
const axes = new THREE.AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 2; // 在网格渲染之后再渲染
node.add(axes);
const grid = new THREE.GridHelper(units, units);
grid.material.depthTest = false;
grid.renderOrder = 1;
node.add(grid);
this.grid = grid;
this.axes = axes;
this.visible = false;
}
get visible() {
return this._visible;
}
set visible(v) {
this._visible = v;
this.grid.visible = v;
this.axes.visible = v;
}
}
function makeAxisGrid(node, label, units) {
const helper = new AxisGridHelper(node, units);
gui.add(helper, "visible").name(label);
}
// makeAxisGrid(solarSystem, "solarSystem", 25);
// makeAxisGrid(sunMesh, "sunMesh");
// makeAxisGrid(earthOrbit, "earthOrbit");
// makeAxisGrid(earthMesh, "earthMesh");
// makeAxisGrid(moonOrbit, "moonOrbit");
// makeAxisGrid(moonMesh, "moonMesh");
}
function render(time) {
time *= 0.001; // convert time to seconds
objects.forEach((obj) => {
obj.rotation.y = time;
// const axes = new THREE.AxesHelper();
// axes.material.depthTest = false;
// axes.renderOrder = 1;
// obj.add(axes);
});
if (resizeRendererToDisplaySize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
</body>
</html>
效果:

2.八大行星
外部模型的加载使用
<html>
<head>
<meta charset="utf-8" />
<title>太阳系八大行星 three.js app</title>
<style>
html,
body {
margin: 0;
height: auto;
overflow-y: auto;
}
#c {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui"></div>
<script
async
src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"
></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.155.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.155.0/examples/jsm/"
}
}
</script>
<script type="module">
//导入
import * as THREE from "three";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
// 响应式处理
function resizeRendererToDisplaySize(renderer) {
// const canvas = renderer.domElement;
const canvas = document.querySelector("#c");
const pixelRatio = window.devicePixelRatio;
const width = (canvas.clientWidth * pixelRatio) | 0;
const height = (canvas.clientHeight * pixelRatio) | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function main() {
const canvas = document.querySelector("#c");
//创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
const gui = new GUI();
// 创建相机
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 50, 0);
camera.lookAt(0, 0, 0);
// 旋转相机
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 5, 0);
controls.update();
// 创建场景
const scene = new THREE.Scene();
// 创建灯光
{
const color = 0xffffff;
const intensity = 500;
const light = new THREE.PointLight(color, intensity);
scene.add(light);
}
// 要更新旋转角度的对象数组
const objects = [];
// 创建场景图
const solarSystem = new THREE.Object3D();
scene.add(solarSystem);
objects.push(solarSystem);
// 创建水星场景
const mercurySystem = new THREE.Object3D();
mercurySystem.position.x = 3.5;
solarSystem.add(mercurySystem);
objects.push(mercurySystem);
// 创建维纳斯场景
const venusSystem = new THREE.Object3D();
venusSystem.position.x = 6;
solarSystem.add(venusSystem);
objects.push(venusSystem);
// 创建地球场景
const earthOrbit = new THREE.Object3D();
earthOrbit.position.x = 10;
solarSystem.add(earthOrbit);
objects.push(earthOrbit);
// 创建金星场景
const marsOrbit = new THREE.Object3D();
marsOrbit.position.x = 13;
solarSystem.add(marsOrbit);
objects.push(marsOrbit);
// 创建jupiter场景
const jupiterOrbit = new THREE.Object3D();
jupiterOrbit.position.x = 15;
solarSystem.add(jupiterOrbit);
objects.push(jupiterOrbit);
// 创建saturn场景
const saturnOrbit = new THREE.Object3D();
saturnOrbit.position.x = 20;
solarSystem.add(saturnOrbit);
objects.push(saturnOrbit);
// 创建uranus场景
const uranusOrbit = new THREE.Object3D();
uranusOrbit.position.x = 24;
solarSystem.add(uranusOrbit);
objects.push(uranusOrbit);
// 创建neptune场景
const neptuneOrbit = new THREE.Object3D();
neptuneOrbit.position.x = 29;
solarSystem.add(neptuneOrbit);
objects.push(neptuneOrbit);
{
//载入太阳
const loader = new GLTFLoader();
// 一球多用
const radius = 1;
const widthSegments = 6;
const heightSegments = 6;
const sphereGeometry = new THREE.SphereGeometry(
radius,
widthSegments,
heightSegments
);
const sunMaterial = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
emissive: 0xffff00,
});
const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const mercuryMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const venusMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const earthMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const marsMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const jupiterMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const saturnMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const uranusMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const neptuneMesh = new THREE.Mesh(sphereGeometry, sunMaterial);
const modelList = [
{
path: "model/sun.glb",
scale: [0.2, 0.2, 0.2],
fatherObj: solarSystem,
mesh: sunMesh,
},
{
path: "model/mercury_enhanced_color.glb",
scale: [0.5, 0.5, 0.5],
fatherObj: mercurySystem,
mesh: mercuryMesh,
},
{
path: "model/venus.glb",
scale: [1, 1, 1],
fatherObj: venusSystem,
mesh: venusMesh,
},
{
path: "model/earth.glb",
scale: [1, 1, 1],
fatherObj: earthOrbit,
mesh: earthMesh,
},
{
path: "model/mars.glb",
scale: [15, 15, 15],
fatherObj: marsOrbit,
mesh: marsMesh,
},
{
path: "model/jupiter.glb",
scale: [1, 1, 1],
fatherObj: jupiterOrbit,
mesh: jupiterMesh,
},
{
path: "model/saturn.glb",
scale: [0.01, 0.01, 0.01],
fatherObj: saturnOrbit,
mesh: saturnMesh,
},
{
path: "model/uranus.glb",
scale: [1, 1, 1],
fatherObj: uranusOrbit,
mesh: uranusMesh,
},
{
path: "model/neptune.glb",
scale: [1, 1, 1],
fatherObj: neptuneOrbit,
mesh: neptuneMesh,
},
];
modelList.forEach((item) => {
loader.load(
item.path,
function (gltf) {
gltf.scene.traverse(function (child) {
if (child.isMesh) {
child.frustumCulled = false;
//模型阴影
child.castShadow = true;
//模型自发光
child.material.emissive = child.material.color;
child.material.emissiveMap = child.material.map;
}
});
gltf.scene.scale.set(...item.scale);
item.fatherObj.add(gltf.scene);
// sunMesh.add(gltf.scene)
objects.push(gltf.scene);
},
undefined,
function (error) {
console.error(error);
}
);
//不使用模型 使用球体
// item.fatherObj.add(item.mesh);
// // sunMesh.add(gltf.scene)
// objects.push(item.mesh);
});
class AxisGridHelper {
constructor(node, units = 10) {
const axes = new THREE.AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 2; // 在网格渲染之后再渲染
node.add(axes);
const grid = new THREE.GridHelper(units, units);
grid.material.depthTest = false;
grid.renderOrder = 1;
node.add(grid);
this.grid = grid;
this.axes = axes;
this.visible = false;
}
get visible() {
return this._visible;
}
set visible(v) {
this._visible = v;
this.grid.visible = v;
this.axes.visible = v;
}
}
function makeAxisGrid(node, label, units) {
const helper = new AxisGridHelper(node, units);
gui.add(helper, "visible").name(label);
}
// makeAxisGrid(solarSystem, "solarSystem", 25);
// makeAxisGrid(sunMesh, "sunMesh");
// makeAxisGrid(earthOrbit, "earthOrbit");
// makeAxisGrid(earthMesh, "earthMesh");
// makeAxisGrid(moonOrbit, "moonOrbit");
// makeAxisGrid(moonMesh, "moonMesh");
}
function render(time) {
time *= 0.001; // convert time to seconds
objects.forEach((obj, index) => {
obj.rotation.y = time;
// obj.rotation.x = time;
// const axes = new THREE.AxesHelper();
// axes.material.depthTest = false;
// axes.renderOrder = 1;
// obj.add(axes);
});
if (resizeRendererToDisplaySize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
</body>
</html>
效果:

今ならできます。
浙公网安备 33010602011771号