中文官网:https://threejs.org/docs/index.html#manual/zh/introduction/Creating-a-scene
学习视频地址:
b站-three.js 学习教程---适合初学者
3D教程 three.js---幽默有趣的demo合集(https://www.youtube.com/c/BrunoSimon/videos:搬运自youtube大佬Bruno Simon的three.js教程)
练习1:月球绕地球转
// 声明全局变量
let camera, scene, renderer;
let moon, earth;
let clock = new THREE.Clock();
// 实例化纹理加载器
const textureLoader = new THREE.TextureLoader();
// 地球和月球半径大小
const EARTH_RADIUS = 2.5;
const MOON_RADIUS = 0.27;
// 实例化相机
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 2000);
camera.position.set(10, 5, 20);
// 实例化场景
scene = new THREE.Scene();
// 创建聚光灯光源
const dirLight = new THREE.SpotLight(0xffffff);
dirLight.position.set(0, 0, 10);
dirLight.intensity = 2;
dirLight.castShadow = true;
scene.add(dirLight);
// 添加环境光
const aLight = new THREE.AmbientLight(0xffffff);
aLight.intensity = 0.3;
scene.add(aLight);
const moonGeometry = new THREE.SphereGeometry(MOON_RADIUS, 16, 16);
const moonMaterial = new THREE.MeshPhongMaterial({
map: textureLoader.load(moonJpg)
})
moon = new THREE.Mesh(moonGeometry, moonMaterial);
moon.receiveShadow = true;
moon.castShadow = true;
scene.add(moon);
// earth
const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS, 16, 16);
const earthMaterial = new THREE.MeshPhongMaterial({
shininess: 5,
map: textureLoader.load(earthJpg),
specularMap: textureLoader.load(earthSJpg),
normalMap: textureLoader.load(earthNJpg)
})
earth = new THREE.Mesh(earthGeometry, earthMaterial);
earth.receiveShadow = true;
earth.castShadow = true;
scene.add(earth);
const earthDiv = document.createElement('div');
earthDiv.className = 'label';
earthDiv.textContent = 'Earth';
const earthLabel = new CSS2DObject(earthDiv);
earthLabel.position.set(0, EARTH_RADIUS - 0.5, 0);
earth.add(earthLabel)
const moonDiv = document.createElement('div');
moonDiv.className = 'label';
moonDiv.textContent = 'Moon';
const moonLabel = new CSS2DObject(moonDiv);
moonLabel.position.set(0, MOON_RADIUS, 0);
moon.add(moonLabel)
// 创建渲染器
renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// 渲染阴影
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
// 标签渲染器
let labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.body.appendChild(labelRenderer.domElement);
// 绑定控制和摄像头
var oldTime = 0;
function animate() {
const elapsed = clock.getElapsedTime();
moon.position.set(Math.sin(elapsed) * 5, 0, Math.cos(elapsed) * 5);
// 地球自传
var axis = new THREE.Vector3(0, 1, 0);
earth.rotateOnAxis(axis, (elapsed - oldTime) * Math.PI / 10);
renderer.render(scene, camera)
labelRenderer.render(scene, camera)
oldTime = elapsed;
requestAnimationFrame(animate)
}
animate();
window.onresize = function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
以上代码是学习视频时记录下来的,并非原创。若想放到vue项目中,将渲染器放到已有div容器中,可将renderer.domElement 添加到已有dom元素中,方便控制宽高.这里,可参见我整理的代码:https://github.com/scrollHeart/threejsDemo