三維坐標(biāo)系A(chǔ)xesHelper xyz軸
- three.js坐標(biāo)軸顏色紅R、綠G陨溅、藍(lán)B分別對應(yīng)坐標(biāo)系的x金矛、y、z軸
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
軌道控制器查看物體OrbitControls
- Orbit controls(軌道控制器)可以使得相機(jī)圍繞目標(biāo)進(jìn)行軌道運(yùn)動呕童。拖動鼠標(biāo)旋轉(zhuǎn)查看各個視角
// 導(dǎo)入軌道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
//添加軌道控制器
const controls = new OrbitControls( camera, renderer.domElement );
//設(shè)置帶阻尼(慢慢停下,有緩沖)
controls.enableDamping = true;
//設(shè)置阻尼系數(shù)
controls.dampingFactor = 0.03;
//自動旋轉(zhuǎn)
controls.autoRotate =true;
controls.update();
設(shè)置響應(yīng)式畫布與全屏控制
//監(jiān)聽窗口變化
window.addEventListener('resize',()=>{
//重置渲染器寬高比
renderer.setSize(window.innerWidth,window.innerHeight);
//重置相機(jī)寬高比
camera.aspect = window.innerWidth/window.innerHeight;
//更新相機(jī)投影矩陣
camera.updateProjectionMatrix();
})
//方法一:自定義按鈕
//點(diǎn)擊按鈕顯示全屏
var btn = document.createElement('button');
btn.innerHTML = '點(diǎn)擊全屏';
btn.style.position = 'absolute';
btn.style.top = '10px';
btn.style.left = '10px';
btn.style.zIndex = '999';
btn.onclick = function(){
//全屏
document.body.requestFullscreen();
console.log('全屏')
}
document.body.appendChild(btn);
//點(diǎn)擊按鈕退出全屏
var exitBtn = document.createElement('button');
exitBtn.innerHTML = '退出全屏';
exitBtn.style.position = 'absolute';
exitBtn.style.top = '10px';
exitBtn.style.left = '100px';
exitBtn.style.zIndex = '999';
exitBtn.onclick = function(){
//退出全屏
document.exitFullscreen();
console.log('退出全屏')
}
document.body.appendChild(exitBtn);
// 導(dǎo)入lil.gui
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js';
let eventObj = {
Fullscreen:function () {
//全屏
document.body.requestFullscreen();
console.log('全屏')
},
ExitFullscreen:function () {
//退出全屏
document.exitFullscreen();
console.log('退出全屏')
}
}
//創(chuàng)建GUI
const gui = new GUI();
//添加按鈕
gui.add(eventObj,"Fullscreen").name("全屏");
gui.add(eventObj,"ExitFullscreen").name("退出全屏");
運(yùn)用GUI面板快速調(diào)試開發(fā)的3D效果
// 導(dǎo)入lil.gui
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js';
//創(chuàng)建GUI
const gui = new GUI();
//添加按鈕
gui.add(eventObj,"Fullscreen").name("全屏");
gui.add(eventObj,"ExitFullscreen").name("退出全屏");
//控制立方體位置
let folder = gui.addFolder("立方體位置") //相當(dāng)于一個文件夾
folder.add(cube.position,"x").min(-10).max(10).step(1).name("立方體x軸的位置").onChange((val) =>{
console.log("立方體x軸的位置:"+val) //onChange()每次拖動都輸出位置
})
folder.add(cube.position,"y").min(-10).max(10).step(1).name("立方體y軸的位置").onFinishChange((val) =>{
console.log("立方體y軸的位置:"+val) //onFinishChange()直接展示最終位置
})
folder.add(cube.position,"z").min(-10).max(10).step(1).name("立方體z軸的位置").onChange((val) =>{
console.log("立方體z軸的位置:"+val)
})
gui.add(parentCubeMaterial,"wireframe").name("父元素線框模式")
//修改立方體顏色
let colorParams = {
cubeColor :"#00ff00" //默認(rèn)顏色
}
gui.addColor(colorParams,"cubeColor").name("立方體顏色").onChange((val) =>{
cube.material.color.set(val)
})
為幾何體劃分頂點(diǎn)組,每個面設(shè)置不同材質(zhì)
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1); //創(chuàng)建立方體
//為每個面設(shè)置不同材質(zhì)
const cubeMaterial0 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cubeMaterial1 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cubeMaterial2 = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const cubeMaterial3 = new THREE.MeshBasicMaterial({ color: 0xffe200 });
const cubeMaterial4 = new THREE.MeshBasicMaterial({ color: 0x0e4930 });
const cubeMaterial5 = new THREE.MeshBasicMaterial({ color: 0xffffff });
const cubeMaterial6 = new THREE.MeshBasicMaterial({ color: 0x000000 });
// 根據(jù)幾何體和材質(zhì)創(chuàng)建物體
const cube = new THREE.Mesh(cubeGeometry,
[cubeMaterial0, cubeMaterial1, cubeMaterial2, cubeMaterial3, cubeMaterial4, cubeMaterial5, cubeMaterial6]
);
// 將幾何體添加到場景中
scene.add(cube);
貼圖
//加載紋理加載器
let textureLoader = new THREE.TextureLoader()
//加載紋理
let texture = textureLoader.load('./texture/1.jpg')
//加載透明貼圖
let alphaMap = textureLoader.load('./texture/2.jpg')
//加載光照貼圖
let lightMap = textureLoader.load('./texture/3.jpg')
//創(chuàng)建幾何體
let planeGeometry = new THREE.PlaneGeometry(1,1)
//創(chuàng)建材質(zhì)
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
map:texture, //添加紋理
transparent:true, //允許透明
alphaMap:alphaMap, //添加透明度貼圖
lightMap:lightMap
})
let plane = new THREE.Mesh(planeGeometry, planeMaterial)
scene.add(plane)
霧Fog
//創(chuàng)建場景霧
//scene.fog = new THREE.Fog(0x999999,0.1,50) //線性霧
scene.fog = new THREE.FogExp2(0x999999,0.1) //指數(shù)霧(霧的密度)
//設(shè)置背景
scene.background = new THREE.Color(0x999999)
加載gltf模型和加載壓縮過的模型
// 導(dǎo)入gltf加載器
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader.js';
// 導(dǎo)入draco壓縮器
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
//實(shí)例化加載器gltf
const gltfLoader = new GLTFLoader();
gltfLoader.load(
//模型路徑
'../model/san_francisco_city_4k.glb',
(gltf)=>{
// console.log(gltf);
scene.add(gltf.scene);
}
)
//創(chuàng)建 加載Draco壓縮
const dracoLoader = new DRACOLoader();
//設(shè)置Draco路徑
dracoLoader.setDecoderPath('./draco/');
//設(shè)置gltf加載器 Draco解碼器
gltfLoader.setDRACOLoader(dracoLoader);
光線投射實(shí)現(xiàn)3D場景交互事件(點(diǎn)擊小球切換顏色)
//創(chuàng)建三個球
const sphere1 = new THREE.Mesh(
new THREE.SphereGeometry(1,32,32),
new THREE.MeshBasicMaterial({
color:0x00ff00
})
)
sphere1.position.x = -4;
scene.add(sphere1)
const sphere2 = new THREE.Mesh(
new THREE.SphereGeometry(1,32,32),
new THREE.MeshBasicMaterial({
color:0x0000ff
})
)
scene.add(sphere2)
const sphere3 = new THREE.Mesh(
new THREE.SphereGeometry(1,32,32),
new THREE.MeshBasicMaterial({
color:0xff00ff
})
)
sphere3.position.x = 4;
scene.add(sphere3)
//創(chuàng)建射線
const raycaster = new THREE.Raycaster()
//創(chuàng)建鼠標(biāo)向量(鼠標(biāo)點(diǎn)在畫布什么位置上)
const mouse = new THREE.Vector2()
//監(jiān)聽鼠標(biāo)
window.addEventListener('click', (event) => {
//輸出每次鼠標(biāo)點(diǎn)擊的位置
//console.log(event.clientX,event.clientY)
//設(shè)置鼠標(biāo)向量的x,y值
mouse.x = (event.clientX / window.innerWidth )* 2 - 1;
mouse.y = -(event.clientY / window.innerHeight )* 2 + 1;
//console.log(mouse.x,mouse.y)
//通過攝像機(jī)和鼠標(biāo)位置更新射線
raycaster.setFromCamera(mouse,camera)
//計算物體與射線的焦點(diǎn)
const intersects = raycaster.intersectObjects([sphere1,sphere2,sphere3])
console.log(intersects)
if(intersects.length > 0){
if(intersects[0].object._isSelect){
intersects[0].object.material.color.set(
intersects[0].object._originColor
)
intersects[0].object._isSelect = false
return
}
intersects[0].object._isSelect = true
intersects[0].object._originColor = intersects[0].object.material.color.getHex()
intersects[0].object.material.color.set(0xff0000)
}
})
補(bǔ)間動畫tween(小球滾動)
//導(dǎo)入tween補(bǔ)間動畫
import * as TWEEN from 'three/examples/jsm//libs/tween.module.js';
//渲染函數(shù)
function animate() {
controls.update();
requestAnimationFrame(animate);
//渲染
renderer.render(scene, camera)
//更新tween
TWEEN.update()
}
animate();
//創(chuàng)建球
const sphere1 = new THREE.Mesh(
new THREE.SphereGeometry(1,32,32),
new THREE.MeshBasicMaterial({
color:0x00ff00
})
)
sphere1.position.x = -4;
scene.add(sphere1)
//移動小球
//創(chuàng)建補(bǔ)間對象
const tween = new TWEEN.Tween(sphere1.position)
tween.to({x:4},2000)
tween.onUpdate(()=>{
//打印小球每次移動的位置
console.log(sphere1.position.x)
}) //2000毫秒
tween.repeat(3) //重復(fù)3次
//tween.repeat(Infinity) //重復(fù)無數(shù)次
tween.yoyo(true)//來回滾動
tween.delay(3000) //延遲3秒后運(yùn)行
//設(shè)置緩動函數(shù)
tween.easing(TWEEN.Easing.Quadratic.InOut) //慢慢加速慢慢減速
const tween2 = new TWEEN.Tween(sphere1.position)
tween2.to({y:-4},1000)
//tween1鏈接tween2,1執(zhí)行完后淆珊,執(zhí)行2
tween.chain(tween2)
//tween2鏈接tween1,2執(zhí)行完后夺饲,執(zhí)行1
tween2.chain(tween)
//啟動補(bǔ)間動畫
tween.start()
tween.onStart(() =>{
console.log('開始')
})
tween.onComplete(() =>{
console.log('結(jié)束')
})
tween.onStop(() =>{
console.log('停止')
})
tween.onUpdate(() =>{
console.log('更新')
})
let params = {
stop:function(){
tween.stop()
}
}
const gui = new GUI()
gui.add(params,"stop")