threejs第一節(jié)

三維坐標(biāo)系A(chǔ)xesHelper xyz軸
  • three.js坐標(biāo)軸顏色紅R、綠G陨溅、藍(lán)B分別對應(yīng)坐標(biāo)系的x金矛、yz
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)式畫布與全屏控制
  • 方法1
//監(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);
image.png
  • 方法2
// 導(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("退出全屏");
image.png
運(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)
})
GUI面板
為幾何體劃分頂點(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)
    }
})
點(diǎn)擊小球變紅色
補(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")
小球滾動并控制停止
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市施符,隨后出現(xiàn)的幾起案子往声,更是在濱河造成了極大的恐慌,老刑警劉巖戳吝,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浩销,死亡現(xiàn)場離奇詭異,居然都是意外死亡听哭,警方通過查閱死者的電腦和手機(jī)慢洋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陆盘,“玉大人普筹,你說我怎么就攤上這事“恚” “怎么了太防?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酸员。 經(jīng)常有香客問我蜒车,道長,這世上最難降的妖魔是什么幔嗦? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任酿愧,我火速辦了婚禮,結(jié)果婚禮上邀泉,老公的妹妹穿的比我還像新娘嬉挡。我一直安慰自己叛氨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布棘伴。 她就那樣靜靜地躺著寞埠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪焊夸。 梳的紋絲不亂的頭發(fā)上仁连,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音阱穗,去河邊找鬼饭冬。 笑死,一個胖子當(dāng)著我的面吹牛揪阶,可吹牛的內(nèi)容都是我干的昌抠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼鲁僚,長吁一口氣:“原來是場噩夢啊……” “哼炊苫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冰沙,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤侨艾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拓挥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唠梨,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年侥啤,在試婚紗的時候發(fā)現(xiàn)自己被綠了当叭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡盖灸,死狀恐怖蚁鳖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情糠雨,我是刑警寧澤才睹,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布徘跪,位于F島的核電站甘邀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏垮庐。R本人自食惡果不足惜松邪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哨查。 院中可真熱鬧逗抑,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至褂傀,卻和暖如春忍啤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悍抑,地道東北人氓奈。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像售滤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容