国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue3集成ThreeJS實(shí)現(xiàn)3D效果,threejs+Vite+Vue3+TypeScript 實(shí)戰(zhàn)課程【一篇文章精通系列】

這篇具有很好參考價(jià)值的文章主要介紹了Vue3集成ThreeJS實(shí)現(xiàn)3D效果,threejs+Vite+Vue3+TypeScript 實(shí)戰(zhàn)課程【一篇文章精通系列】。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

項(xiàng)目簡介

這是一個(gè)使用Vue3,TypeScript,Vite和Three.js的項(xiàng)目。Vue3是一個(gè)流行的JavaScript框架,用于構(gòu)建用戶界面。TypeScript是一種靜態(tài)類型的編程語言,它是JavaScript的超集,可以編譯成純JavaScript。Vite是一個(gè)由Evan You開發(fā)的新的前端構(gòu)建工具,能夠提供快速的冷啟動和即時(shí)熱更新。

Three.js是一個(gè)輕量級的3D庫,能夠讓我們在任何瀏覽器中創(chuàng)建和顯示動畫的3D計(jì)算機(jī)圖形。在該項(xiàng)目中,我們將Three.js集成到了Vue3和TypeScript的環(huán)境中,使得我們可以在Vue組件中使用Three.js來創(chuàng)建3D圖形。

此外,項(xiàng)目中還可能包含一些封裝了Three.js的代碼,以便于更方便的使用Three.js進(jìn)行3D開發(fā)。

這樣的技術(shù)組合可以讓我們在前端環(huán)境中實(shí)現(xiàn)復(fù)雜的3D可視化效果,為項(xiàng)目增加更豐富的視覺體驗(yàn)。

??3D模型下載網(wǎng)站:https://sketchfab.com/feed
??3D人物動作綁定:www.mixamo.com
??3D角色生產(chǎn)工具:https://readyplayer.me/
??模型壓縮網(wǎng)站:gltf.report
??查找天空背景:google key words: equirectangular sky / skybox background
??材質(zhì)貼圖素材:https://www.textures.com
??hdr素材庫(環(huán)境貼圖): https://polyhaven.com
??二次元風(fēng)3D角色生產(chǎn)軟件VRoid Studio: https://vroid.com/en/studio

??Sketchfab公用賬號:
Login: lingo3dchina@gmail.com
PW: Lingo3dxoxo
Code:640841

一、項(xiàng)目初始化

npm install -g vite


npm init vite@latest threejs-vite-vue -- --template vue


cd threejs-vite-vue

npm install

npm run dev

項(xiàng)目創(chuàng)建成功
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript注意threejs的版本

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript "@types/three": "^0.155.1",

項(xiàng)目創(chuàng)建成功在IDE當(dāng)中導(dǎo)入項(xiàng)目

1、添加一些依賴項(xiàng)

npm install vue-router

npm install three

npm install @types/three -D

npm install ant-design-vue

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascriptvue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript創(chuàng)建一些路由相關(guān)
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascriptvue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascriptvue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import {createRouter,createWebHistory,RouteRecordRaw} from "vue-router";
const routes: RouteRecordRaw[] = [
]
const router = createRouter({
    history:createWebHistory(),
    routes
})
router.beforeEach((to)=>{
    document.title = 'three+vite+vue3'+to.meta.title as string
})

export default router

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import { createApp } from 'vue'
import './style.css';
import Antd from 'ant-design-vue';
import App from './App.vue';
import router from './router/index';
import 'ant-design-vue/dist/reset.css';

let app = createApp(App)
app.use(router)
app.use(Antd)
app.mount('#app')

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascriptvue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import {RouteRecordRaw} from "vue-router";
const chapter1 : RouteRecordRaw[] = [
]

export default chapter1;

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import {createRouter,createWebHistory,RouteRecordRaw} from "vue-router";
import chapter1 from "./chapter1";
const routes: RouteRecordRaw[] = [
    ...chapter1
]
const router = createRouter({
    history:createWebHistory(),
    routes
})
export default router

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <router-view></router-view>
</template>
<script setup>
</script>
<style scoped>
</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <div>
    第一個(gè)場景
  </div>
</template>
<script>
export default {
  name: "index"
}
</script>
<style scoped>
</style>

二、創(chuàng)建3D【基礎(chǔ)搭建】

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

.container{
    width: 100vw;
    height: 100vh;
}

1、繪制板子,立方體,球體

Three.js來繪制一個(gè)簡單的3D場景,包括一個(gè)平面(板子)、一個(gè)立方體和一個(gè)球體
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <div ref="containerRef" class="container">
  </div>
</template>
<script lang="ts" setup>
import {onMounted, ref} from "vue";
import {
  AxesHelper, BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene, SphereGeometry,
  WebGLRenderer
} from "three";

const containerRef = ref<HTMLDivElement>()
//創(chuàng)建場景
const scene = new Scene();
//創(chuàng)建攝像機(jī)
const camera = new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
//設(shè)置攝像機(jī)位置
camera.position.set(-30,40,30)
//設(shè)置攝像機(jī)朝向
camera.lookAt(scene.position)

//重置webGL的顏色
const renderer =  new WebGLRenderer();
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)

//添加坐標(biāo)系
const ases = new AxesHelper(20)
scene.add(ases)

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(60,20);
const meshBasicMaterial = new MeshBasicMaterial({color:0xcccccc});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)

plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0
scene.add(plane)

//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshBasicMaterial({color:0xff0000,wireframe:true})
const cube = new Mesh(cubeGeometry,cubeMaterial)
cube.position.set(2,2,2)
scene.add(cube)

//繪制球體,設(shè)置球體的半徑為4
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshBasicMaterial({
  color: 0x7777ff,
  wireframe:true
})
const sphere = new Mesh(sphereGeometry,sphereMaterial)
sphere.position.x = 15
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)

onMounted(()=>{
  //設(shè)置攝像頭朝向
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene,camera)
})

</script>
<style scoped>

</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

2、材質(zhì)和光照

在Three.js中,材質(zhì)和光照是讓物體看起來更為真實(shí)的關(guān)鍵因素。材質(zhì)定義了物體表面的外觀,如顏色、紋理和光照效果。Three.js提供了多種類型的材質(zhì),適用于不同的光照效果。

物理基礎(chǔ)渲染(Physically Based Rendering, PBR)是一種基于物理的渲染技術(shù),使用物理基礎(chǔ)渲染代碼和材料處理技術(shù)來模擬光線和材料之間的物理相互作用,以創(chuàng)建逼真的材料外觀和光照效果。這種渲染技術(shù)可以提供更真實(shí)的陰影,高光,反射和漫反射效果,使場景看起來更加真實(shí)。Three.js核心也包含了與Unreal、Unity、Disney和Pixar等巨頭使用的相同的基于物理的渲染 (PBR) 算法。

對于紋理的應(yīng)用,可以通過加載圖片并設(shè)置其重復(fù)模式、采樣模式以及重復(fù)次數(shù)來實(shí)現(xiàn)貼圖效果。例如,創(chuàng)建一個(gè)地平面,并用下方展示的 2x2 像素的黑白格圖片來作為紋理。首先加載這個(gè)紋理,設(shè)置重復(fù)模式(wrapS, wrapT),采樣模式(magFilter)以及重復(fù)的次數(shù)。因?yàn)橘N圖是 2x2 大小,通過設(shè)置成平鋪模式,并且重復(fù)次數(shù)是邊長的一半,就可以讓每個(gè)格子正好是1個(gè)單位的大小。

設(shè)置導(dǎo)航菜單組件
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <a-menu mode="horizontal" style="position: fixed">
    <a-sub-menu key="demo">
      <template #title>
        第一章
      </template>
      <a-menu-item key="1">
        <router-link to="/"> 第一個(gè)場景 </router-link>
      </a-menu-item>
      <a-menu-item key="2">
        <router-link to="/chapter1/2"> 第一個(gè)場景 </router-link>
      </a-menu-item>
    </a-sub-menu>
  </a-menu>
  <router-view></router-view>
</template>
<script setup>
</script>
<style scoped>
</style>

復(fù)制index,生成index2
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <div ref="containerRef" class="container">
  </div>
</template>
<script lang="ts" setup>
import {onMounted, ref} from "vue";
import {
  AxesHelper, BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene, SphereGeometry,
  WebGLRenderer
} from "three";

const containerRef = ref<HTMLDivElement>()
//創(chuàng)建場景
const scene = new Scene();
//創(chuàng)建攝像機(jī)
const camera = new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
//設(shè)置攝像機(jī)位置
camera.position.set(-30,40,30)
//設(shè)置攝像機(jī)朝向
camera.lookAt(scene.position)

//重置webGL的顏色
const renderer =  new WebGLRenderer();
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)

//添加坐標(biāo)系
const ases = new AxesHelper(20)
scene.add(ases)

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(60,20);
const meshBasicMaterial = new MeshBasicMaterial({color:0xcccccc});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)

plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0
scene.add(plane)

//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshBasicMaterial({color:0xff0000,wireframe:true})
const cube = new Mesh(cubeGeometry,cubeMaterial)
cube.position.set(2,2,2)
scene.add(cube)

//繪制球體,設(shè)置球體的半徑為4
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshBasicMaterial({
  color: 0x7777ff,
  wireframe:true
})
const sphere = new Mesh(sphereGeometry,sphereMaterial)
sphere.position.x = 15
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)

onMounted(()=>{
  //設(shè)置攝像頭朝向
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene,camera)
})






</script>
<style scoped>

</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import {RouteRecordRaw} from "vue-router";
import Index from '../lesson/chapter1/index.vue'
import Index2 from '../lesson/chapter1/index2.vue'

const chapter1 : RouteRecordRaw[] = [
    {
        path:'/',
        component: Index,
        meta:{
            title:"第一個(gè)場景"
        }
    },
    {
        path:'/chapter1/2',
        component: Index2,
        meta:{
            title:"第二個(gè)場景"
        }
    }
]
export default chapter1;

實(shí)現(xiàn)第二個(gè)場景

<template>
  <div ref="containerRef" class="container">
  </div>
</template>
<script lang="ts" setup>
import {onMounted, ref} from "vue";
import {
  AxesHelper, BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial, MeshLambertMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene, SphereGeometry, SpotLight,
  WebGLRenderer
} from "three";

const containerRef = ref<HTMLDivElement>()
//創(chuàng)建場景
const scene = new Scene();
//創(chuàng)建攝像機(jī)
const camera = new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
//設(shè)置攝像機(jī)位置
camera.position.set(-30,40,30)
//設(shè)置攝像機(jī)朝向
camera.lookAt(scene.position)

//重置webGL的顏色
const renderer =  new WebGLRenderer();
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.shadowMap.enabled = true

const spotLight = new SpotLight(0xffffff)
spotLight.castShadow = true
spotLight.position.set(-40,60,-10)
scene.add(spotLight)

//添加坐標(biāo)系
const axes = new AxesHelper(20)
scene.add(axes)

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(60,20);
const meshBasicMaterial = new MeshLambertMaterial({color:0xcccccc});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)
plane.receiveShadow = true //設(shè)置可以接收陰影
plane.rotation.x = -0.5 * Math.PI;
//plane.position.x = 15
//plane.position.y = 0
//plane.position.z = 0

scene.add(plane)


//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube = new Mesh(cubeGeometry,cubeMaterial)
cube.castShadow = true
cube.position.set(2,2,2)
scene.add(cube)

//繪制球體,設(shè)置球體的半徑為4
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({
  color: 0x7777ff,
  wireframe:false
})

const sphere = new Mesh(sphereGeometry,sphereMaterial)
sphere.castShadow = true
sphere.position.x = 15
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)

onMounted(()=>{
  //設(shè)置攝像頭朝向
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene,camera)
})

</script>
<style scoped>

</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

3、材質(zhì)和光照和動畫

Three.js提供了一套強(qiáng)大的動畫系統(tǒng),可以應(yīng)用于物體的位置、旋轉(zhuǎn)、縮放、材質(zhì)的顏色或不透明度等各個(gè)方面。這套系統(tǒng)中主要包括了KeyFrameTrack、AnimationClip、AnimationMixer和AnimationAction四個(gè)組件。

在制作動畫時(shí),我們通常會使用關(guān)鍵幀動畫,即在不同時(shí)間點(diǎn)設(shè)置關(guān)鍵幀,然后由動畫系統(tǒng)通過補(bǔ)間過程自動填補(bǔ)各關(guān)鍵幀之間的變化。例如,要為一個(gè)彈跳的球設(shè)置動畫,只需要指定彈跳的頂部和底部的點(diǎn),Three.js將在這兩點(diǎn)之間的所有點(diǎn)上平滑地生成動畫。此外,我們還可以通過合成和混合多個(gè)動畫來創(chuàng)造出更復(fù)雜的效果。
復(fù)制index2創(chuàng)建index3
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <div ref="containerRef" class="container">
  </div>
</template>
<script lang="ts" setup>
import {onMounted, ref} from "vue";
import {
  AxesHelper, BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial, MeshLambertMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene, SphereGeometry, SpotLight,
  WebGLRenderer
} from "three";

const containerRef = ref<HTMLDivElement>()
//創(chuàng)建場景
const scene = new Scene();
//創(chuàng)建攝像機(jī)
const camera = new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
//設(shè)置攝像機(jī)位置
camera.position.set(-30,40,30)
//設(shè)置攝像機(jī)朝向
camera.lookAt(scene.position)

//重置webGL的顏色
const renderer =  new WebGLRenderer();
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.shadowMap.enabled = true

const spotLight = new SpotLight(0xffffff)
spotLight.castShadow = true
spotLight.position.set(-40,60,-10)
scene.add(spotLight)

//添加坐標(biāo)系
const axes = new AxesHelper(20)
scene.add(axes)

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(100,50);
const meshBasicMaterial = new MeshLambertMaterial({color:0xcccccc});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)
plane.receiveShadow = true //設(shè)置可以接收陰影
plane.rotation.x = -0.5 * Math.PI;
//plane.position.x = 15
//plane.position.y = 0
//plane.position.z = 0

scene.add(plane)


//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube = new Mesh(cubeGeometry,cubeMaterial)
cube.castShadow = true
cube.position.set(2,2,2)
scene.add(cube)


//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry1 = new BoxGeometry(4,4,4)
const cubeMaterial1 = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube1 = new Mesh(cubeGeometry1,cubeMaterial1)
cube1.castShadow = true
cube1.position.set(-10,2,2)
scene.add(cube1)



//繪制球體,設(shè)置球體的半徑為4
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({
  color: 0x7777ff,
  wireframe:false
})

const sphere = new Mesh(sphereGeometry,sphereMaterial)
sphere.castShadow = true
sphere.position.x = 15
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)


//控制物體運(yùn)動
let step = 0;

function renderScene() {
  step += 0.04;

  cube.rotation.x += 0.02;
  cube.rotation.y += 0.02;
  cube.rotation.z += 0.02;

  cube1.rotation.x += -0.02;
  cube1.rotation.y += -0.02;
  cube1.rotation.z += -0.02;
  cube1.scale.set((2 + 1 * Math.cos(step)), (2 + 1 * Math.cos(step)), (2 + 1 * Math.cos(step)));

  //控制物體
  sphere.position.x = 20 + 10 * Math.cos(step); //cos為數(shù)據(jù)當(dāng)中的函數(shù) 余弦函數(shù)
  sphere.position.y = 2 + 10 * Math.abs(Math.sin(step));  //abs為絕對值  sin為正弦函數(shù)

  requestAnimationFrame(renderScene)
  renderer.render(scene,camera)
}
renderScene()

onMounted(()=>{
  //設(shè)置攝像頭朝向
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene,camera)
})

</script>
<style scoped>

</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

4、性能監(jiān)控

Three.js的性能監(jiān)控工具Stats.js是一個(gè)強(qiáng)大的插件,它能夠監(jiān)測幀率、內(nèi)存等數(shù)據(jù)的變化。在動畫或網(wǎng)頁開發(fā)中,幀率是衡量和描述動畫是否流暢的一個(gè)重要單位。Stats.js可以幫助開發(fā)者實(shí)時(shí)了解Three.js的渲染性能,尤其是渲染幀率(FPS),即每秒鐘完成的渲染次數(shù)。理想狀態(tài)下,渲染幀率應(yīng)該達(dá)到每秒60次。

在使用Stats.js時(shí),首先需要引入相關(guān)的腳本文件。然后,實(shí)例化一個(gè)Stats對象,并將該對象生成的DOM元素添加到頁面中。通過這種方式,我們可以在開發(fā)過程中實(shí)時(shí)監(jiān)控Three.js的性能,及時(shí)發(fā)現(xiàn)并解決可能存在的問題,從而提升用戶體驗(yàn)。

安裝stats.js插件

npm install stats.js

復(fù)制index3.vue創(chuàng)建index4.vue
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

    import index4 from '../lesson/chapter1/index4.vue'

    ,
    {
        path:'/chapter1/4',
        component: index4,
        meta:{
            title:"性能監(jiān)控"
        }
    }

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

 <div ref="statsRef"></div>

const statsRef = ref<HTMLDivElement>()

const stats = new Stats()
stats.showPanel(0)

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

  stats.update()

  //創(chuàng)建場景
  const scene = new Scene();
  stats.dom.style.top = "50px"
  statsRef.value?.append(stats.dom)

訪問第四個(gè)場景
http://127.0.0.1:5173/chapter1/4

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

5、交互控制

dat.gui@0.7.9是一個(gè)輕量級的JavaScript庫,它的主要功能是幫助用戶添加交互式控制面板,以便在3D場景中調(diào)整對象參數(shù)并實(shí)時(shí)預(yù)覽結(jié)果。

復(fù)制一下index4.vue 為index5.vue
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

 {
        path:'/chapter1/5',
        component: index5,
        meta:{
            title:"交互控制"
        }
    }

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

     <a-menu-item key="5">
        <router-link to="/chapter1/5"> 第五個(gè)場景 </router-link>
      </a-menu-item>

安裝dat.gui

npm install dat.gui@0.7.9

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

npm install @types/dat.gui@0.7.9 -D

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import * as dat from "dat.gui"

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

const controlRef = ref({
  rotationSpeed:0.02,
  bouncingSpeed:0.03,
})
const gui = new dat.GUI();
gui.add(controlRef.value,"rotationSpeed",0,0.5)
gui.add(controlRef.value,"bouncingSpeed",0,0.5)



  step += 0.04;

  cube.rotation.x += controlRef.value.rotationSpeed;
  cube.rotation.y += controlRef.value.rotationSpeed;
  cube.rotation.z += controlRef.value.rotationSpeed;

  cube1.rotation.x += -controlRef.value.rotationSpeed;
  cube1.rotation.y += -controlRef.value.rotationSpeed;
  cube1.rotation.z += -controlRef.value.rotationSpeed;

  step += controlRef.value.bouncingSpeed;


vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
放置重復(fù)初始化

if(document.querySelectorAll(".dg.ac>.dg.main.a").length === 0){
  const gui = new dat.GUI()
  gui.add(controlRef.value,"rotationSpeed",0,0.5)
  gui.add(controlRef.value,"bouncingSpeed",0,0.5)
}

index5.vue全部代碼

<template>
  <div ref="statsRef"></div>
  <div ref="containerRef" class="container">
  </div>
</template>
<script lang="ts" setup>
import {onMounted, ref} from "vue";
import {
  AxesHelper, BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial, MeshLambertMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene, SphereGeometry, SpotLight,
  WebGLRenderer
} from "three";
import Stats from "stats.js"
import * as dat from "dat.gui"

const containerRef = ref<HTMLDivElement>()
const statsRef = ref<HTMLDivElement>()

const stats = new Stats()
stats.showPanel(0)

//創(chuàng)建場景
const scene = new Scene();
//創(chuàng)建攝像機(jī)
const camera = new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
//設(shè)置攝像機(jī)位置
camera.position.set(-30,40,30)
//設(shè)置攝像機(jī)朝向
camera.lookAt(scene.position)

//重置webGL的顏色
const renderer =  new WebGLRenderer();
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.shadowMap.enabled = true

const spotLight = new SpotLight(0xffffff)
spotLight.castShadow = true
spotLight.position.set(-40,60,-10)
scene.add(spotLight)

//添加坐標(biāo)系
const axes = new AxesHelper(20)
scene.add(axes)

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(100,50);
const meshBasicMaterial = new MeshLambertMaterial({color:0xcccccc});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)
plane.receiveShadow = true //設(shè)置可以接收陰影
plane.rotation.x = -0.5 * Math.PI;
//plane.position.x = 15
//plane.position.y = 0
//plane.position.z = 0

scene.add(plane)


//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube = new Mesh(cubeGeometry,cubeMaterial)
cube.castShadow = true
cube.position.set(2,2,2)
scene.add(cube)


//繪制立方體,設(shè)置板子的長寬高分別是4,4,4
const cubeGeometry1 = new BoxGeometry(4,4,4)
const cubeMaterial1 = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube1 = new Mesh(cubeGeometry1,cubeMaterial1)
cube1.castShadow = true
cube1.position.set(-10,2,2)
scene.add(cube1)



//繪制球體,設(shè)置球體的半徑為4
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({
  color: 0x7777ff,
  wireframe:false
})

const sphere = new Mesh(sphereGeometry,sphereMaterial)
sphere.castShadow = true
sphere.position.x = 15
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)

const controlRef = ref({
  rotationSpeed:0.02,
  bouncingSpeed:0.03,
})

if(document.querySelectorAll(".dg.ac>.dg.main.a").length === 0){
  const gui = new dat.GUI()
  gui.add(controlRef.value,"rotationSpeed",0,0.5)
  gui.add(controlRef.value,"bouncingSpeed",0,0.5)
}

//控制物體運(yùn)動
let step = 0;

function renderScene() {

  stats.update()

  step += 0.04;

  cube.rotation.x += controlRef.value.rotationSpeed;
  cube.rotation.y += controlRef.value.rotationSpeed;
  cube.rotation.z += controlRef.value.rotationSpeed;

  cube1.rotation.x += -controlRef.value.rotationSpeed;
  cube1.rotation.y += -controlRef.value.rotationSpeed;
  cube1.rotation.z += -controlRef.value.rotationSpeed;

  step += controlRef.value.bouncingSpeed;

  cube1.scale.set((2 + 1 * Math.cos(step)), (2 + 1 * Math.cos(step)), (2 + 1 * Math.cos(step)));
  //控制物體
  sphere.position.x = 20 + 10 * Math.cos(step); //cos為數(shù)據(jù)當(dāng)中的函數(shù) 余弦函數(shù)
  sphere.position.y = 2 + 10 * Math.abs(Math.sin(step));  //abs為絕對值  sin為正弦函數(shù)

  requestAnimationFrame(renderScene)
  renderer.render(scene,camera)
}
renderScene()

onMounted(()=>{

  //創(chuàng)建場景
  const scene = new Scene();
  stats.dom.style.top = "50px"
  statsRef.value?.append(stats.dom)

  //設(shè)置攝像頭朝向
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene,camera)
})

</script>
<style scoped>

</style>

6、響應(yīng)窗口變化

和之前一樣創(chuàng)建index6.vue
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

/*
監(jiān)聽在窗口變化的時(shí)候重新設(shè)置大小
* */
window.addEventListener('resize',()=>{
  camera.aspect = window.innerWidth / window.innerHeight;
  //更新相機(jī)投影矩陣
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth,window.innerHeight)
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

三、基礎(chǔ)場景搭建

1、創(chuàng)建基礎(chǔ)場景【實(shí)現(xiàn)添加幾何體和刪除幾何體】

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
將index6復(fù)制到chapter2下的index

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


const controlRef = ref({
  rotationSpeed:0.02,
  bouncingSpeed:0.03,
  numberOfObjects:0,
  addCube:function (){
    //繪制立方體,設(shè)置板子的長寬高分別是4,4,4
    const cubeGeometry = new BoxGeometry(4,4,4)
    const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
    const cube = new Mesh(cubeGeometry,cubeMaterial)
    cube.name = "cube-"+scene.children.length
    cube.castShadow = true
    cube.position.x = -30 + Math.round((Math.random() * 60))
    cube.position.y =  Math.round((Math.random() * 5))
    cube.position.z = -20 + Math.round((Math.random() * 40))
    scene.add(cube)
    this.numberOfObjects = scene.children.length
  },
  removeCube:function (){
    const allChildren = scene.children;
    const lastObject = allChildren[allChildren.length - 1];
    if(lastObject instanceof Mesh && lastObject.name.startsWith('cube')){
      scene.remove(lastObject);
    }
    this.numberOfObjects = scene.children.length
  }
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


if(document.querySelectorAll(".dg.ac>.dg.main.a").length === 0){
  const gui = new dat.GUI()
  gui.add(controlRef.value,"addCube")
  gui.add(controlRef.value,"removeCube")
  gui.add(controlRef.value,"numberOfObjects").listen()
  gui.add(controlRef.value,"rotationSpeed",0,0.5)
  gui.add(controlRef.value,"bouncingSpeed",0,0.5)

}

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


  stats.update()

  //遍歷場景當(dāng)中的所有內(nèi)容
  scene.traverse((e) =>{
    /*
    * 
    if ( e instanceof Mesh && e != plane){
      e.rotation.x += controlRef.value.rotationSpeed;
      e.rotation.y += controlRef.value.rotationSpeed;
      e.rotation.z += controlRef.value.rotationSpeed;
    }
    */

    if ( e.name.startsWith('cube')){
      e.rotation.x += controlRef.value.rotationSpeed;
      e.rotation.y += controlRef.value.rotationSpeed;
      e.rotation.z += controlRef.value.rotationSpeed;
    }
  })

實(shí)現(xiàn)點(diǎn)擊添加cube和刪除cube
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

2、實(shí)現(xiàn)霧化場景

霧化效果是一種常見的視覺效果,它可以使場景中的物體看起來更加模糊和透明。在Three.js中,可以通過設(shè)置材質(zhì)的透明度和混合模式來實(shí)現(xiàn)霧化效果
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

addFog:function (){
    scene.fog = new Fog(0xffffff,0.015,100)
    this.numberOfObjects = scene.children.length
  }
gui.add(controlRef.value,"addFog")

http://127.0.0.1:5173/chapter2/2
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
移除霧化
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

removeFog:function (){
    scene.fog = null
  }
  gui.add(controlRef.value,"removeFog")

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

3、重寫材質(zhì)

在Three.js中,材質(zhì)是定義物體外觀的關(guān)鍵。通過創(chuàng)建自定義材質(zhì),可以對物體的外觀進(jìn)行更精細(xì)的控制,包括如何設(shè)置材質(zhì)的顏色、紋理和透明度等屬性。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

toggleMaterial:function (){
    if(!scene.overrideMaterial){
      scene.overrideMaterial = new MeshLambertMaterial({
        color:0xffffff,
      })
    }else{
      scene.overrideMaterial =null
    }
  }

 gui.add(controlRef.value,"toggleMaterial")

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

4、常見幾何體

在Three.js中,幾何體是一個(gè)數(shù)據(jù)結(jié)構(gòu),它包含了用于描述三維物體的基本信息,如頂點(diǎn)(vertices)、線(lines)和面(faces)。幾何體可以被用來定義物體的形狀和大小。

常見的幾何體類型有以下幾種:

BoxGeometry(立方體幾何體):通過指定寬度、高度和深度來創(chuàng)建一個(gè)立方體。
SphereGeometry(球體幾何體):通過指定半徑來創(chuàng)建一個(gè)球體。
CylinderGeometry(圓柱體幾何體):通過指定高度、半徑和圓周上的段數(shù)來創(chuàng)建一個(gè)圓柱體。
PlaneGeometry(平面幾何體):一種基礎(chǔ)的二維幾何體,可以用來繪制平面。
ConeGeometry(圓錐體幾何體):通過指定高度、底部半徑和頂部半徑,以及圓周上的段數(shù)來創(chuàng)建一個(gè)圓錐體。
TubularGeometry(管狀幾何體):這是一種具有圓形截面的管道形狀,需要指定管道的中心軸線、直徑、高度和圓周上的段數(shù)。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


const geoms:BufferGeometry[] = []
geoms.push(new CylinderGeometry(1,4,8))
geoms.push(new BoxGeometry(2,2,2))
geoms.push(new OctahedronGeometry(3))
geoms.push(new TetrahedronGeometry(3))
geoms.push(new TorusGeometry(3,1,10,10))
//材質(zhì)
const materials = [
  new MeshLambertMaterial({
    color:Math.random() * 0xffffff,
    flatShading:true
  }),
  new MeshBasicMaterial({
    color: 0x000000,
    wireframe:true
  })
]
geoms.forEach((g,i) =>{
  const mesh = createMultiMaterialObject(g,materials)
  mesh.castShadow = true
  mesh.position.x = -24 + i * 10,
  mesh.position.y = 4,
  scene.add(mesh)
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

5、修改幾何體屬性

在Three.js中,幾何體的屬性可以通過修改其頂點(diǎn)、線和面的數(shù)據(jù)來改變物體的形狀和大小。以下是一些常見的修改幾何體屬性的方法:

修改頂點(diǎn)數(shù)據(jù):通過修改幾何體的vertices屬性,可以改變物體的形狀。例如,可以將一個(gè)立方體的頂點(diǎn)數(shù)據(jù)修改為一個(gè)球體的頂點(diǎn)數(shù)據(jù),從而創(chuàng)建一個(gè)球形物體。

修改線數(shù)據(jù):通過修改幾何體的lines屬性,可以改變物體的邊界線。例如,可以將一個(gè)立方體的邊線修改為一個(gè)圓柱體的邊線,從而創(chuàng)建一個(gè)圓柱形物體。

修改面數(shù)據(jù):通過修改幾何體的faces屬性,可以改變物體的表面。例如,可以將一個(gè)立方體的面修改為一個(gè)球體的面,從而創(chuàng)建一個(gè)球形物體。

修改材質(zhì)屬性:通過修改幾何體的material屬性,可以改變物體的顏色、紋理和透明度等視覺效果。例如,可以將一個(gè)立方體的材質(zhì)修改為一個(gè)半透明的紅色材料,從而創(chuàng)建一個(gè)半透明的紅色立方體。

需要注意的是,修改幾何體屬性需要對Three.js的底層實(shí)現(xiàn)有一定的了解,并且需要注意性能問題。如果頻繁地修改幾何體屬性,可能會導(dǎo)致性能下降。因此,在實(shí)際應(yīng)用中,應(yīng)該根據(jù)需求選擇合適的方法來修改幾何體屬性。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

scaleX:1,
  scaleY:1,
  scaleZ:1,
  positionX:1,
  positionY:1,
  positionZ:1,
  translateZ:1,
  translateY:1,
  translateX:1,
  obj:{
    x:0,
    y:0,
    z:0,
  },
  translate:function (){
    this.obj.x = this.translateX
    this.obj.y = this.translateY
    this.obj.z = this.translateZ
  }

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

/*設(shè)置大小*/
  const scaleFolder = gui.addFolder("scale")
  scaleFolder.add(controlRef.value,"scaleX",0,5);
  scaleFolder.add(controlRef.value,"scaleY",0,5);
  scaleFolder.add(controlRef.value,"scaleZ",0,5);
  /*設(shè)置位置*/
  const positionFolder = gui.addFolder("position")
  positionFolder.add(controlRef.value,"positionX",-5,5);
  positionFolder.add(controlRef.value,"positionY",-5,5);
  positionFolder.add(controlRef.value,"positionZ",-5,5);

  /*設(shè)置斜角位置*/
  const translateFolder = gui.addFolder("translate")
  translateFolder.add(controlRef.value,"translateX",-5,5);
  translateFolder.add(controlRef.value,"translateY",-5,5);
  translateFolder.add(controlRef.value,"translateZ",-5,5);
  translateFolder.add(controlRef.value,"translate");

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

watch(()=>controlRef.value.obj,(n)=>{
  cube.translateX(n.x)
  cube.translateY(n.y)
  cube.translateZ(n.z)
},{deep:true})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

6、相機(jī)切換

在Three.js中,相機(jī)是用于渲染場景的工具。主要包括透視相機(jī)(PerspectiveCamera)和正交相機(jī)(OrthographicCamera)。

透視相機(jī)可以創(chuàng)建具有深度感的三維效果,而正交相機(jī)則可以在二維平面上進(jìn)行投影。

實(shí)現(xiàn)相機(jī)視角的切換,主要有兩種方法。一種是使用Tween.js庫來實(shí)現(xiàn)平滑過渡的效果。Tween.js庫可以很容易實(shí)現(xiàn)兩個(gè)值之間的過度,中間值都會自動計(jì)算出來。

另一種是通過鼠標(biāo)拉拽來改變相機(jī)的位置、旋轉(zhuǎn)角度等,比如使用OrbitControls類。

OrbitControls類是Three.js提供的鼠標(biāo)、方向鍵與場景交互的控件,通過鼠標(biāo)的操作可以改變相機(jī)的視角,從而改變視覺,使得視覺效果更具有真實(shí)感。

此外,如果想要切換不同的場景,可以通過創(chuàng)建多個(gè)場景對象,并在每個(gè)場景中添加不同的模型、燈光等元素。

使用renderer.render(scene, camera)方法在渲染循環(huán)中渲染當(dāng)前場景,使用scene.dispose()方法清除當(dāng)前場景中的元素,釋放內(nèi)存。當(dāng)需要切換到下一個(gè)場景時(shí),重復(fù)上述步驟,并將下一個(gè)場景設(shè)置為當(dāng)前場景。

設(shè)置場景和多個(gè)物體
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

//繪制板子,設(shè)置板子的寬度為60,設(shè)置板子的高度為20
const planeGeometry = new PlaneGeometry(100,50,1);
const meshBasicMaterial = new MeshLambertMaterial({color:0xffffff});//設(shè)置材質(zhì)顏色
const plane = new Mesh(planeGeometry,meshBasicMaterial)
plane.receiveShadow = true //設(shè)置可以接收陰影
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0

scene.add(plane)

const cubeGeometryC = new BoxGeometry(4,4,4)
const cubeMaterialC = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube = new Mesh(cubeGeometryC,cubeMaterialC)
cube.castShadow = true
cube.position.set(2,2,2)
scene.add(cube)

for (let j = 0;j < planeGeometry.parameters.height / 2;j++){
  for (let i = 0;i < planeGeometry.parameters.width / 2;i++){
    const cube = new Mesh(cubeGeometryC,cubeMaterialC)
    cube.position.z = -(planeGeometry.parameters.height / 2) + 2 + j * 5;
    cube.position.x = -(planeGeometry.parameters.height / 2) + 2 + i * 5;
    cube.position.y = 0;
    scene.add(cube)
  }
}

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

設(shè)置切換相機(jī)
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

 gui.add(controlRef.value,"camera").listen()
  gui.add(controlRef.value,"switchCamera")

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

watch(()=>controlRef.value.camera,(n)=>{
  if(n === 'Orthographic'){
    cameraRef.value = new OrthographicCamera(window.innerWidth / -16 ,window.innerWidth / 16 ,window.innerHeight / 16 ,window.innerHeight / -16,-200,500 )
    cameraRef.value.position.set(-120,60,180)
    cameraRef.value.lookAt(scene.position)
  }else{
    cameraRef.value = new PerspectiveCamera(45,window.innerWidth / window.innerHeight ,0.1,1000 )
    cameraRef.value.position.set(-120,60,180)
    cameraRef.value.lookAt(scene.position)
  }
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

7、相機(jī)跟隨

在Three.js中,相機(jī)跟隨物體的技術(shù)廣泛應(yīng)用于實(shí)現(xiàn)如游戲中的攝像機(jī)跟隨角色、VR中的視點(diǎn)跟蹤等效果。

要實(shí)現(xiàn)這一功能,首先需要獲取到目標(biāo)物體(例如一個(gè)游戲角色或者一個(gè)3D模型)的位置信息,然后將相機(jī)的位置設(shè)置為該物體的對應(yīng)位置,從而實(shí)現(xiàn)視角的跟隨。

此外,關(guān)于具體的實(shí)現(xiàn)方式,有多種可選的策略。

如果你想要?jiǎng)?chuàng)建一個(gè)第一人稱視角的效果,可以使用鍵盤的WASD鍵控制相機(jī)的移動方向;而如果你希望實(shí)現(xiàn)第三人稱視角的效果,則可以通過鼠標(biāo)來控制相機(jī)的視角朝向。

另外,對于復(fù)雜的場景,比如管道內(nèi)的視野展示或者物體在三維空間中任意方向移動的情況,你可能需要結(jié)合使用一些額外的工具和方法。

例如,你可以創(chuàng)建一個(gè)管道模型來幫助你觀察物體的運(yùn)動方向,并通過調(diào)整相機(jī)的位置和朝向,使得鏡頭能夠緊密地跟隨物體的移動。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


const lookAtGeom = new SphereGeometry(20)
const lookAtMesh = new Mesh(
    lookAtGeom,
    new MeshLambertMaterial({
      color:0xff0000
    })
)
scene.add(lookAtMesh)

//控制物體運(yùn)動
let step = 0;

function renderScene() {

  stats.update()

  if (cameraRef.value){
    step += 0.01
    const x = 10 + 100 * Math.sin(step)
    cameraRef.value.lookAt(new Vector3(x,10,0))  // Vector3是三維的坐標(biāo)

    lookAtMesh.position.copy(new Vector3(x,10,0))
    cameraRef.value.lookAt(new Vector3(x,10,0))

    renderer.render(scene,cameraRef.value)
  }
}  

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

四、光照

1、環(huán)境光

Three.js中環(huán)境光(AmbientLight)是一種全局光照,它能夠均勻地照亮場景中的物體。

與點(diǎn)光源和平行光源不同,環(huán)境光不會直接照亮物體,而是與場景中的顏色相乘,從而使得物體的顏色變暗或變亮。

環(huán)境光通常用于模擬全局的光照效果,例如在室外場景中模擬太陽的光線、室內(nèi)場景中模擬燈光的反射等。

通過調(diào)整環(huán)境光的顏色和強(qiáng)度,可以改變整個(gè)場景的亮度和色調(diào),從而增強(qiáng)渲染的真實(shí)感。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

ambientColor:"#0c0c0c"



const ambientLight = new AmbientLight(controlRef.value.ambientColor)
scene.add(ambientLight)

watch(()=>controlRef.value.ambientColor,(n)=>{
  ambientLight.color = new Color(n)
})

gui.addColor(controlRef.value,"ambientColor")

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

2、點(diǎn)光源

Three.js庫中的THREE.PointLight(點(diǎn)光源)是一種單點(diǎn)發(fā)光、照射所有方向的光源,比如夜空中的照明彈。

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

 ambientColor:"#0c0c0c",
  pointColor:"#ccffcc",
  distance: 100,
const pointLight = new PointLight(controlRef.value.pointColor)
pointLight.distance = 100
pointLight.position.copy(lookAtMesh.position)
scene.add(pointLight)

watch(
    () => controlRef.value.pointColor,
    () => {
      pointLight.color = new Color(controlRef.value.pointColor)
    }
)
watch(
    () => controlRef.value.distance,
    () => {
      pointLight.distance = controlRef.value.distance
    }
)
 gui.addColor(controlRef.value,"pointColor")
  gui.add(controlRef.value,"distance",-1000,1000)

3、聚光燈

Three.js中的聚光燈(SpotLight)是一種光源類型,用于在場景中創(chuàng)建聚焦光照。

它有一個(gè)錐形的照射范圍,可以模擬手電筒或燈塔等發(fā)出的光線。

聚光燈具有方向和角度,可以通過調(diào)整其屬性來控制照射范圍和強(qiáng)度
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

target:'plane',

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


watch(
    () => controlRef.value.target,
    (t) => {
      if(t === 'cube'){
        spotLight.target = cube
      }else if( t === 'sphere'){
        spotLight.target = sphere
      }else {
        spotLight.target = plane
      }
    }
)

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

4、平行光

Three.js中的平行光(DirectionalLight)是一種光源類型,它發(fā)出的光線是平行的并且沿特定方向傳播。

這種光源模擬太陽光等效果,因?yàn)樗谋憩F(xiàn)像是無限遠(yuǎn),從它發(fā)出的光線都是平行的。平行光通常用于模擬太陽光、月光等遠(yuǎn)離物體的光源。

你可以通過調(diào)整平行光的顏色、強(qiáng)度以及方向?qū)傩詠砜刂普丈湫Ч?/p>

在著色器中計(jì)算時(shí),平行光的方向向量會直接與模型頂點(diǎn)的法線方向進(jìn)行點(diǎn)乘操作,從而確定該點(diǎn)的亮度。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

//添加平行光
const directionalColor = "#ff5808"
const directionalLight = new DirectionalLight(directionalColor)
directionalLight.position.set(-40,60,-10)
directionalLight.castShadow = true
directionalLight.intensity = 0.5
scene.add(directionalLight)

5、半球光

Three.js中的半球光(HemisphereLight)是一種光源類型,它模擬了天空和地面的反射效果。這種光源的特性在于,其發(fā)出的光線顏色從天空光線顏色漸變到地面光線顏色。

具體來說,半球光的原理由兩部分組成,一部分是從下往上的平行光,另一部分是從上半球往中心點(diǎn)的光。

這樣,實(shí)現(xiàn)了模擬模型法線向上的部分天空光線照射到物體上,法線向下的部分接收來自于地面的反射環(huán)境光。

然而需要注意的是,半球光無法投射陰影。

在創(chuàng)建半球光時(shí),可以分別指定天空和地面的顏色。
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

//添加半球光
// 創(chuàng)建球體幾何體和材質(zhì)
const sphereGeometry1 = new SphereGeometry(2, 32, 32);
const sphereMaterial1 = new MeshLambertMaterial({
  color: 0x7777ff,
  wireframe:false
})
// 創(chuàng)建網(wǎng)格對象并添加到場景中
const spherea = new  Mesh(sphereGeometry1, sphereMaterial1);
scene.add(spherea);
// 渲染循環(huán)
function animate() {
  requestAnimationFrame(animate);
  // 更新球體材質(zhì)的emissive屬性以實(shí)現(xiàn)半球光效果
  const time = Date.now() * 0.001;
  sphereMaterial.emissive.setRGB(Math.sin(time) * 0.5 + 0.5, Math.cos(time) * 0.5 + 0.5, Math.sin(time * 2) * 0.5 + 0.5);
  renderer.render(scene, camera);
}
animate();


vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

五、小車案例

1、基礎(chǔ)環(huán)境搭建

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

<template>
  <div ref="statsRef"></div>
  <div ref="containerRef" class="container">
  </div>
</template>

<script lang="ts" setup>

import {
  ACESFilmicToneMapping, AxesHelper,
  Color,
  EquirectangularReflectionMapping, Fog, GridHelper, Material,
  PerspectiveCamera,
  Scene,
  sRGBEncoding,
  WebGLRenderer
} from "three";
import Stats from "stats.js"
import * as dat from "dat.gui"
import {onMounted, ref, watchEffect} from "vue";
//
import venice_sunset_1k from '../../assets/venice_sunset_1k.hdr?url'
import car from '../../assets/car.glb?url'
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader";

const scene = new Scene();

const grid = new GridHelper(20,40,0xfffff,0xffff);

const containerRef = ref<HTMLDivElement>()
const statsRef = ref<HTMLDivElement>()

const stats = new Stats();
const controlRef = ref({
  bodyColor:"#0c0c0c",
  glassColor:"#0c0c0c",
  detailColor:"#0c0c0c",
})
const cameraRef = ref<PerspectiveCamera>()
const rendererRef = ref<WebGLRenderer>()

//它會檢查當(dāng)前網(wǎng)頁中是否存在具有特定類名(即".dg.ac>.dg.main.a")的元素。
// 如果不存在,它將創(chuàng)建一個(gè)新的dat.GUI對象,
// 并在該對象中添加三個(gè)顏色控件:bodyColor、glassColor和detailColor。
// 這些顏色控件的值都是從名為controlRef的引用所指向的對象中獲取的
function initGUI() {
  if(document.querySelectorAll(".dg.ac>.dg.main.a").length === 0){
    const gui = new dat.GUI()
    gui.addColor(controlRef.value,"bodyColor")
    gui.addColor(controlRef.value,"glassColor")
    gui.addColor(controlRef.value,"detailColor")
  }
}
/*
它使用PerspectiveCamera構(gòu)造函數(shù)創(chuàng)建了一個(gè)新的透視相機(jī)對象。
這個(gè)構(gòu)造函數(shù)需要四個(gè)參數(shù):視角角度(在這里為45度)、縱橫比(在這里為窗口寬度除以窗口高度)、近裁剪平面距離(在這里為0.1)
以及遠(yuǎn)裁剪平面距離(在這里為1000)。然后,它設(shè)置了攝像機(jī)的位置坐標(biāo)為(-30,40,30),使攝像機(jī)面向場景的位置
* */
function initCamera() {
  cameraRef.value =  new PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
  cameraRef.value.position.set(-30,40,30)
  cameraRef.value.lookAt(scene.position)
}

/*

創(chuàng)建了一個(gè)新的WebGL渲染器并將其賦值給rendererRef。這個(gè)渲染器啟用了抗鋸齒功能,
設(shè)置了像素比例為窗口的設(shè)備像素比,
并將寬度和高度設(shè)置為窗口的內(nèi)寬度和內(nèi)高度。它還設(shè)置了輸出編碼為sRGBEncoding,
色調(diào)映射為ACESFilmicToneMapping,色調(diào)映射曝光為0.85。

* */
function initRenderer(){
  rendererRef.value = new WebGLRenderer({antialias:true})

  rendererRef.value.setPixelRatio(window.devicePixelRatio)
  rendererRef.value.setSize(window.innerWidth,window.innerHeight)
  rendererRef.value.outputEncoding = sRGBEncoding
  rendererRef.value.toneMapping = ACESFilmicToneMapping
  rendererRef.value.toneMappingExposure = 0.85
}

/*
將背景顏色設(shè)為深灰色(#333),然后加載名為"venice_sunset_1k"的環(huán)境貼圖,并將其映射方式設(shè)為EquirectangularReflectionMapping。這將會使場景具有反射光照的效果。

接下來的幾行代碼修改了grid組件所用材質(zhì)的透明度、深度寫入以及透明度屬性,使其呈現(xiàn)出半透明效果。

最后,它向場景中添加了一個(gè)長度為20的新坐標(biāo)軸助手。
*
*/
function initScene(){
  scene.background = new Color(0x333333)
  scene.environment = new RGBELoader().load(venice_sunset_1k)
  scene.environment.mapping = EquirectangularReflectionMapping;
 // scene.fog = new Fog(0x333333,10,15)

  const material = grid.material as Material
  material.opacity = 0.2
  material.depthWrite = false
  material.transparent = true
  scene.add(grid)

  const axes = new AxesHelper(20)
  scene.add(axes)

}

initGUI()
onMounted(()=>{
  //創(chuàng)建場景
  stats.dom.style.top = "50px"
  statsRef.value?.append(stats.dom)
  initScene()
  initCamera()
  initRenderer()
})

/*
持續(xù)運(yùn)行的循環(huán)渲染函數(shù),用于不斷更新和重新繪制3D場景。

每一幀開始時(shí),它會先調(diào)用stats對象的update方法,用于統(tǒng)計(jì)當(dāng)前性能信息。

接著,它會調(diào)用requestAnimationFrame方法再次請求下一幀的動畫。這個(gè)方法會在瀏覽器認(rèn)為適合的時(shí)候安排一次重繪,通常是在下一次刷新周期之前。

如果存在cameraRef引用,則使用該相機(jī)進(jìn)行當(dāng)前幀的渲染。rendererRef指針表示的是已經(jīng)初始化好的WebGL渲染器,而scene則是需要渲染的三維場景。

最后,根據(jù)性能計(jì)數(shù)器的時(shí)間戳,對網(wǎng)格物體的位置做了一次平移操作,使得網(wǎng)格能夠以一定的速度沿Z軸方向移動。這里使用了取模運(yùn)算符%來讓網(wǎng)格的位置在其運(yùn)動過程中始終保持在一個(gè)范圍內(nèi)。

注意requestAnimationFrame(renderScene)這一句的作用。這是一個(gè)JavaScript API,它可以在瀏覽器下次重繪之前,要求瀏覽器執(zhí)行指定的函數(shù)(在這個(gè)例子中就是renderScene())。這樣做的好處是可以減少不必要的CPU和GPU工作,從而提高頁面性能。

每個(gè)requestAnimationFrame()調(diào)用都會返回一個(gè)定時(shí)ID,你可以用這個(gè)ID取消未執(zhí)行的動畫。如果要停止動畫,只需清除對應(yīng)的定時(shí)ID即可。

在這個(gè)例子中,requestAnimationFrame(renderScene)會在每次渲染完成后立即調(diào)用自己,從而形成一個(gè)無限循環(huán),不斷地重復(fù)執(zhí)行渲染過程。只要頁面沒有關(guān)閉,這個(gè)函數(shù)就會一直被調(diào)用下去。
* */
function renderScene() {
  stats.update()
  requestAnimationFrame(renderScene)
  if(cameraRef.value){
    rendererRef.value!.render(scene,cameraRef.value)
  }
  const time = -performance.now() / 1000
  grid.position.z = -(time) % 1
}

renderScene()

/*
這段代碼是一個(gè)Vue watchEffect鉤子函數(shù),當(dāng)某些數(shù)據(jù)發(fā)生變化時(shí),會觸發(fā)此函數(shù)執(zhí)行。

函數(shù)內(nèi)部主要做了兩件事:

將rendererRef的domElement屬性(即渲染器的DOM元素)添加到containerRef指定的容器中。這意味著該渲染器將會在對應(yīng)的HTML元素中顯示。
在窗口大小發(fā)生改變時(shí),監(jiān)聽并響應(yīng)事件。當(dāng)窗口尺寸發(fā)生改變時(shí),會更新相機(jī)的寬高比,計(jì)算新的投影矩陣,并且重新設(shè)置渲染器的尺寸,使其與窗口尺寸保持一致。
因此,這段代碼的作用是將渲染結(jié)果正確地顯示出來,并確保在窗口尺寸改變時(shí)能夠及時(shí)更新視口大小和視角。
* */
watchEffect(()=>{
  containerRef.value?.appendChild(rendererRef.value!.domElement)
  window.addEventListener('resize',()=>{
    cameraRef.value!.aspect = window.innerWidth / window.innerHeight
    //更新相投影矩陣
    cameraRef.value!.updateProjectionMatrix();
    rendererRef.value!.setSize(window.innerWidth,window.innerHeight)
  },false)
})

</script>

<style scoped>

</style>

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

2、載入模型,實(shí)現(xiàn)軌道控制器

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

import venice_sunset_1k from '../../assets/venice_sunset_1k.hdr?url'
import Car from '../../assets/car.glb?url'

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

//軌道控制器
const controlsRef = ref<OrbitControls>()

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


function initGLTF() {
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath('/gltf/');
  const  loader = new GLTFLoader();
  loader.setDRACOLoader (dracoLoader) ;
  loader.load(Car,(gltf: GLTF) => {
    console.log(gltf)
    const carModel = gltf.scene.children[0];
    scene.add(carModel)
  })
}

function initControl() {
  if(cameraRef.value) {
    controlsRef.value = new OrbitControls(cameraRef.value,containerRef.value);
    controlsRef.value.enableDamping = true
    controlsRef.value.maxDistance = 9
    controlsRef.value.target.set(0,0.5,0)
    controlsRef.value.update()
  }
}
initGUI()
initGLTF()
onMounted(()=>{
  //創(chuàng)建場景
  stats.dom.style.top = "50px"
  statsRef.value?.append(stats.dom)
  initScene()
  initCamera()
  initRenderer()
  initControl()
})

3、實(shí)現(xiàn)模型顏色材質(zhì)調(diào)整,輪子轉(zhuǎn)動

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

//軌道控制器
const controlsRef = ref<OrbitControls>()
const bodyMaterial = new MeshPhysicalMaterial({
  color:0xff0000,metalness:1.0,roughness:0.5,clearcoat:1.0,clearcoatRoughness:0.03,sheen:0.5
})
const glassMaterial = new MeshPhysicalMaterial({
  color:0xffffff,metalness:0.25,roughness:0,transmission:1.0
})
const detailMaterial = new MeshPhysicalMaterial({
  color:0xff0000,metalness:1.0,roughness:0.5
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript



watch(()=> controlRef.value.bodyColor,(c)=>{
  bodyMaterial.color.set(c);
})
watch(()=> controlRef.value.glassColor,(c)=>{
  glassMaterial.color.set(c);
})
watch(()=> controlRef.value.detailColor,(c)=>{
  detailMaterial.color.set(c);
})

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

  const carModel = gltf.scene.children[0];
    (carModel.getObjectByName('body') as Mesh).material = bodyMaterial;
    (carModel.getObjectByName('glass') as Mesh).material = glassMaterial;
    (carModel.getObjectByName('rim_fl') as Mesh).material = detailMaterial;
    (carModel.getObjectByName('rim_fr') as Mesh).material = detailMaterial;
    (carModel.getObjectByName('rim_rr') as Mesh).material = detailMaterial;
    (carModel.getObjectByName('rim_rl') as Mesh).material = detailMaterial;
    (carModel.getObjectByName('trim') as Mesh).material = detailMaterial;
    wheels.push(
        carModel.getObjectByName('wheel_fl'),
        carModel.getObjectByName('wheel_fr'),
        carModel.getObjectByName('wheel_rl'),
        carModel.getObjectByName('wheel_rr'),
    )

vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript


  for (let i = 0;i < wheels.length;i++){
    wheels[i]!.rotation.x = time * Math.PI * 2
  }

實(shí)現(xiàn)效果
vue3 typescript threejs,Vue,TypeScript,threejs,3d,typescript,javascript

4、源代碼下載

https://download.csdn.net/download/qq_44757034/88582419文章來源地址http://www.zghlxwxcb.cn/news/detail-770614.html

到了這里,關(guān)于Vue3集成ThreeJS實(shí)現(xiàn)3D效果,threejs+Vite+Vue3+TypeScript 實(shí)戰(zhàn)課程【一篇文章精通系列】的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • vue基于threejs實(shí)現(xiàn)的3D可視化編輯器

    vue基于threejs實(shí)現(xiàn)的3D可視化編輯器

    隨著5G網(wǎng)絡(luò)的漸漸普及,物聯(lián)網(wǎng)在人們的生活中漸漸廣泛使用,社會向著越來越智能化的方向發(fā)展。當(dāng)康科技經(jīng)過不懈努力,研發(fā)屬于自己的一款3D可視化編輯器,助力企業(yè)應(yīng)用實(shí)現(xiàn)3D可視化服務(wù)。 編輯器界面如下: 操作視頻演示: 3D可視化編輯器v1.0版本完成 主要功能點(diǎn)如下

    2024年02月13日
    瀏覽(25)
  • ThreeJS-VUE-3DMax 實(shí)現(xiàn)Web3D(簡單測試)

    ThreeJS-VUE-3DMax 實(shí)現(xiàn)Web3D(簡單測試)

    ? ? ? ? 今天使用3DMax建模軟件進(jìn)行3D模型的制作,并且加入動畫,通過threejs將模型及其動畫部署在VUE框架上。 ? ? ? ? 1. VUE:3.3.4 ? ? ? ? 2. threejs:0.158.0 ? ? ? ? 3. vite:4.4.11 ? ? ? ? 4. 3DMax2021 ? ? ? ? 5. pycharm2021專業(yè)版 ? ? ? ? 簡單制作一個(gè)小植物和一個(gè)水壺,實(shí)現(xiàn)澆

    2024年02月03日
    瀏覽(21)
  • threejs+vue 省份3D可視化地圖

    threejs+vue 省份3D可視化地圖

    1.先獲取想要展示地圖的區(qū)域json數(shù)據(jù) 阿里云獲取地圖區(qū)域的json 示例為陜西省 2.npm安裝three.js和d3 npm i three 、 npm i d3 3.引入相關(guān)方法和json數(shù)據(jù) 該文章只做記錄,具體在場景中使用中自己調(diào)整。

    2024年04月14日
    瀏覽(24)
  • vue3+vite項(xiàng)目集成mars3d

    創(chuàng)建一個(gè)項(xiàng)目 yarn create vite // vue - ts 安裝依賴 yarn add?vite-plugin-mars3d -D yarn add?mars3d 控制臺警告 warning \\\" mars3d@3.5.0\\\" has unmet peer dependency \\\"@turf/turf@^6.5.0\\\". warning \\\" mars3d@3.5.0\\\" has unmet peer dependency \\\"mars3d-cesium@~1.103.1\\\". 安裝 yarn add? @turf/turf?mars3d-cesium 修改 vite.config.ts 修改srcApp.vue 就可

    2024年02月15日
    瀏覽(31)
  • vue3 + vite + ts 集成mars3d

    vue3 + vite + ts 集成mars3d

    使用mars3d過程中,需要集成mars3d到自己的項(xiàng)目中,mars3d開發(fā)教程中已經(jīng)有集成好的項(xiàng)目模板 http://mars3d.cn/doc.html 項(xiàng)目模板gitte地址:https://gitee.com/marsgis/mars3d-vue-template/tree/master/mars3d-vue3-vite 如果不想用官方的模板就需要自己集成 如何創(chuàng)建項(xiàng)目參考網(wǎng)上的教程,這里就不做詳細(xì)

    2024年02月06日
    瀏覽(38)
  • Threejs實(shí)現(xiàn)3d地球記錄(4)

    Threejs實(shí)現(xiàn)3d地球記錄(4)

    Three.js基礎(chǔ)曲線函數(shù)有三種: 樣條曲線:在三維空間中設(shè)置5個(gè)頂點(diǎn),輸入三維樣條曲線CatmullRomCurve3函數(shù)作為參數(shù),然后返回更多個(gè)頂點(diǎn),通過返回的頂點(diǎn)數(shù)據(jù),構(gòu)建一個(gè)幾何體,然后繪制出來一條沿著5個(gè)頂點(diǎn)的光滑樣條曲線。 三維三次貝賽爾曲線: 由起點(diǎn)、終點(diǎn)、及兩個(gè)

    2024年02月02日
    瀏覽(19)
  • threejs 實(shí)現(xiàn)場景漫游效果(相機(jī)沿著自定義軌道移動)

    threejs 實(shí)現(xiàn)場景漫游效果(相機(jī)沿著自定義軌道移動)

    效果視頻: Video_22-06-15_18-10-11 實(shí)現(xiàn)思路:先創(chuàng)建一條曲線curve作為運(yùn)動路線,然后使用const points = curve.getPoints(n)方法將curve分成n-1段;我們可以通過points[n] 獲取第n個(gè)點(diǎn)的坐標(biāo)位置;將相機(jī)的位置設(shè)置為這個(gè)坐標(biāo),在動畫中不斷地修改n的值達(dá)到移動的效果;具體操作如下:

    2024年02月11日
    瀏覽(93)
  • 智慧城市炫酷效果、threejs繪制道路、shader實(shí)現(xiàn)道路流光效果

    智慧城市炫酷效果、threejs繪制道路、shader實(shí)現(xiàn)道路流光效果

    1、數(shù)據(jù)準(zhǔn)備

    2024年02月13日
    瀏覽(19)
  • Threejs實(shí)現(xiàn)WebVR全景小行星入場動畫/魚眼效果/球形展開效果

    Threejs實(shí)現(xiàn)WebVR全景小行星入場動畫/魚眼效果/球形展開效果

    1,功能介紹 使用 Threejs實(shí)現(xiàn)WebVR全景,VR全景小行星入場動畫、魚眼效果、由遠(yuǎn)到近效果、球形展開動畫效果。如下效果圖: 這種效果其實(shí)很簡單,通過修改 像機(jī)視錐體垂直視野角度fov,和相機(jī)的坐標(biāo)位置 實(shí)現(xiàn)動畫效果,鼠標(biāo)拖動查看使用 軌道控制器OrbitControls.js 2,功能實(shí)現(xiàn)

    2024年02月11日
    瀏覽(22)
  • 手把手教 Vue3.2+Vite+Echarts 5 繪制3D線條效果中國地圖

    手把手教 Vue3.2+Vite+Echarts 5 繪制3D線條效果中國地圖

    本篇文章介紹 Vue3.2+Vite 項(xiàng)目內(nèi)使用 Echarts 5 繪制中國地圖,標(biāo)記分布點(diǎn)!之前沒有接觸過 Echarts 的,可以先去官方示例看看,里面圖形特別齊全。但是官方文檔看著費(fèi)勁的,太多了根本記不住,所以自己做個(gè)總結(jié),下次就可以直接使用了,不用做重復(fù)無用功。 1、下載并引入

    2024年02月04日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包