最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Three.js中如何使用CSS3DRenderer和CSS3DSprite實現(xiàn)模型標簽文字

 更新時間:2024年05月21日 11:04:11   作者:前端嗎嘍  
在Three.js中,使用CSS3DRenderer和CSS3DSprite可以輕松地實現(xiàn)模型標簽文字的效果,為場景中的模型提供更直觀的信息展示,本文將介紹如何使用這兩個工具來實現(xiàn)模型標簽文字,并提供相應的代碼示例,感興趣的朋友跟隨小編一起看看吧

導語

Three.js中,使用CSS3DRendererCSS3DSprite可以輕松地實現(xiàn)模型標簽文字的效果,為場景中的模型提供更直觀的信息展示。本文將介紹如何使用這兩個工具來實現(xiàn)模型標簽文字,并提供相應的代碼示例。

引言

Three.js是一款強大的JavaScript 3D庫,用于在Web上創(chuàng)建交互式的3D圖形應用程序。在Three.js中,CSS3DRendererCSS3DSprite是兩個重要的工具,它們可以用于在3D場景中渲染HTML元素,為用戶提供更豐富的交互體驗。

實現(xiàn)的效果

在Three.js中使用CSS3DRenderer和CSS3DSprite實現(xiàn)模型標簽文字

實現(xiàn)模型標簽文字的步驟

步驟一、導入所需庫

// Three.js庫
import * as THREE from 'three'; 
 // CSS3DRenderer用于渲染CSS3D對象
import { CSS3DRenderer, CSS3DSprite } from "three/examples/jsm/renderers/CSS3DRenderer.js";

步驟二、初始化CSS3DRenderer

const labelRenderer = new CSS3DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight); // 設置渲染器尺寸
labelRenderer.domElement.style.position = 'absolute'; // 設置渲染器樣式
labelRenderer.domElement.style.top = '0'; // 設置渲染器樣式
document.body.appendChild(labelRenderer.domElement); // 將渲染器掛載到頁面上

步驟三、創(chuàng)建css3D標簽

const div = document.createElement('div');
div.className = 'workshop-text'; // 添加樣式類
div.innerHTML = '<p>浮法車間</p>'; // 添加標簽文字

步驟四、創(chuàng)建CSS3DSprite對象

const sprite = new CSS3DSprite(div);
sprite.position.set(8, 3, 42); // 設置標簽位置,這里根據(jù)模型具體位置調(diào)整

步驟五、將CSS3DSprite添加到模型中,并通過GUI控制器控制文字位置

object.add(sprite); // object是模型對象,這里需要替換為實際的模型對象
// 在GUI中添加文件夾用于調(diào)整標簽位置
const tagFolder = gui.addFolder('浮法車間標簽');
tagFolder.add(sprite.position, 'x', -200, 200).name('X Position'); // 調(diào)整標簽x位置
tagFolder.add(sprite.position, 'y', -200, 200).name('Y Position'); // 調(diào)整標簽y位置
tagFolder.add(sprite.position, 'z', -200, 200).name('Z Position'); // 調(diào)整標簽z位置
tagFolder.open(); // 打開文件夾,默認顯示控制器

所有代碼:

<template>
  <!-- 用于展示Three.js場景的HTML容器 -->
  <div id="my-three"></div>
</template>
<script setup>
import { ref, onMounted, getCurrentInstance } from 'vue'
import * as THREE from 'three' // 導入Three.js庫
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' // 導入軌道控制器以實現(xiàn)場景的旋轉、縮放等交互
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; // 導入GLTF模型加載器
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { CSS3DRenderer, CSS3DSprite } from "three/examples/jsm/renderers/CSS3DRenderer.js";
const { proxy } = getCurrentInstance(); // 獲取當前Vue組件實例
const gui = new GUI();
// 設置cube紋理加載器,立方體紋理加載器
const cubeTextureLoader = new THREE.CubeTextureLoader();
// 設置環(huán)境貼圖
const envMapTexture = cubeTextureLoader.load([
  "../../public/posx.jpg",
  "../../public/negx.jpg",
  "../../public/posy.jpg",
  "../../public/negy.jpg",
  "../../public/posz.jpg",
  "../../public/negz.jpg",
]);
onMounted(() => {
  document.getElementById('my-three')?.appendChild(renderer.domElement) // 將渲染器的DOM元素掛載到頁面上
  init() // 初始化場景、相機和光源
  renderModel()  // 設置渲染參數(shù)
  gltfModel1() // 加載GLTF模型
  render() // 啟動渲染循環(huán)
})
// 定義場景寬度和高度
const width = window.innerWidth, height = window.innerHeight;
const scene = new THREE.Scene(); // 創(chuàng)建場景
const renderer = new THREE.WebGLRenderer() // 創(chuàng)建渲染器
const loader = new GLTFLoader(); // 創(chuàng)建GLTF加載器
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000); // 創(chuàng)建透視相機
const controls = new OrbitControls(camera, renderer.domElement) // 創(chuàng)建控制器
let glbModel;
function init() {
  // 光源設置
  const ambient = new THREE.AmbientLight(0xffffff, 0.5); // 添加環(huán)境光
  scene.add(ambient);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);// 添加平行光
  directionalLight.position.set(95, 585, 39); // 設置光源位置
  scene.add(directionalLight);
  //設置相機位置
  camera.position.set(-20, 300, 700); // 設置相機位置
  //設置相機方向
  camera.lookAt(0, 0, 0); // 設置相機朝向場景中心
  //輔助坐標軸
  const axesHelper = new THREE.AxesHelper(200);//參數(shù)200標示坐標系大小,可以根據(jù)場景大小去設置
  scene.add(axesHelper);
  // 設置場景背景色
  // scene.background = envMapTexture;
  // 設置渲染器像素比,適應設備分辨率
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.antialias = true;
  // 初始化 GUI 控件
  const camFolder = gui.addFolder('Camera');
  camFolder.add(camera.position, 'x', -6500, 6500, 10).name('X Axis');
  camFolder.add(camera.position, 'y', -6500, 6500, 10).name('Y Axis');
  camFolder.add(camera.position, 'z', -6500, 6500, 10).name('Z Axis');
  camFolder.open();
  const lightFolder = gui.addFolder('Light');
  lightFolder.add(directionalLight.position, 'x', -6500, 6500).name('X Axis');
  lightFolder.add(directionalLight.position, 'y', -6500, 6500).name('Y Axis');
  lightFolder.add(directionalLight.position, 'z', -6500, 6500).name('Z Axis');
  lightFolder.add(directionalLight, 'intensity', 0, 1).name('Intensity');
  lightFolder.open();
  // 設置渲染器參數(shù)
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  renderer.toneMappingExposure = 2.5;
  // 初始化 CSS3DRenderer
  const labelRender = new CSS3DRenderer();
  labelRender.setSize(window.innerWidth, window.innerHeight);
  labelRender.domElement.style.position = 'absolute';
  labelRender.domElement.style.top = '0px';
  labelRender.domElement.style.pointerEvents = 'none';
  document.getElementById('my-three').appendChild(labelRender.domElement);
  proxy.labelRender = labelRender;
  // 更新控制器
  controls.update();
}
function gltfModel1() {
  // 加載GLTF模型
  loader.load("../../public/yuanqu.glb",
    function (gltf) { // 模型加載完成后的回調(diào)函數(shù)
      glbModel = gltf.scene;
      scene.add(gltf.scene) // 將模型添加到場景中
      glbModel.traverse((object) => {
        if (object.name === "fufachejian") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>浮法車間</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 42); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('浮法車間標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "bangongqu") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>辦公樓</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 78); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('辦公區(qū)標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "qiye_01") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>企業(yè)1</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 38); // 調(diào)整標簽位置
          object.add(tag);
        }
        if (object.name === "qiye_002") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>企業(yè)2</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(12, 5, 54); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('qiye--------');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "chejian_06") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>車間6</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 38); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('食堂標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "chejian_03") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>倉庫3</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 38); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('食堂標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "chejian_02") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>倉庫2</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 38); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('食堂標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "chejian_01") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>倉庫1</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(8, 3, 38); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('食堂標簽');
          // // 將tag.position對象中的x, y, z屬性添加到GUI中
          // tagFolder.add(tag.position, 'x', -200, 200).name('X Position');
          // tagFolder.add(tag.position, 'y', -200, 200).name('Y Position');
          // tagFolder.add(tag.position, 'z', -200, 200).name('Z Position');
          // tagFolder.open(); // 打開此文件夾以默認顯示控制器
        }
        if (object.name === "yuanliaolou") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>原料樓</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(-10, -1, 38); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          const tagFolder = gui.addFolder('食堂標簽');
        }
        if (object.name === "qizhan") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>氣站</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(-10, -1, 20); // 調(diào)整標簽位置
          object.add(tag);
          // 在GUI中添加一個用于調(diào)整tag位置的文件夾
          // const tagFolder = gui.addFolder('食堂標簽');
        }
        if (object.name === "yuanpian") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          div.innerHTML = '<p>原片倉庫</p>';
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(-6, 7, 30); // 調(diào)整標簽位置
          object.add(tag);
        }
        if (object.name === "yuchuli002" || object.name === "yuchuli003" || object.name === "yuchuli") {
          const div = document.createElement('div');
          div.className = 'workshop-text';
          if (object.name === "yuchuli002") {
            div.innerHTML = '<p>預處理車間1</p>';
          } else if(object.name === "yuchuli003") {
            div.innerHTML = '<p>預處理車間2</p>';
          }else if(object.name === "yuchuli"){
            div.innerHTML = '<p>預處理車間1</p>';
          }
          // 創(chuàng)建CSS3DSprite
          const tag = new CSS3DSprite(div);
          tag.position.set(-6, 7, 30); // 調(diào)整標簽位置
          object.add(tag);
        }
      })
    },
    function (xhr) { // 加載進度回調(diào)
      const percent = Math.floor((xhr.loaded / xhr.total) * 100); // 計算加載進度百分比
      // console.log(`模型加載進度:${percent}%`);
    }
  )
}
function renderModel() {
  //渲染
  renderer.setSize(width, height)//設置渲染區(qū)尺寸
  renderer.render(scene, camera)//執(zhí)行渲染操作、指定場景、相機作為參數(shù)
  // renderer.setClearColor(0x00ff00); // 設置背景顏色為綠色/
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  // 設置曝光度
  renderer.toneMappingExposure = 3; // 適當調(diào)整曝光度
  // 設置控制器的角度限制
  controls.minPolarAngle = Math.PI / 4; // 最小極角為 45 度
  controls.maxPolarAngle = Math.PI / 2; // 最大極角為 90 度
}
//渲染循環(huán)函數(shù)
function render() {
  renderer.render(scene, camera); // 執(zhí)行渲染操作
  controls.update() // 更新控制器
  proxy.labelRender.render(scene, camera); // 渲染 CSS3D 標簽
  requestAnimationFrame(render); // 請求下一幀
}
// 畫布跟隨窗口變化
window.onresize = function () {
  renderer.setSize(window.innerWidth, window.innerHeight); // 重設渲染器尺寸
  camera.aspect = window.innerWidth / window.innerHeight;  // 更新相機的長寬比
  camera.updateProjectionMatrix(); // 更新相機的投影矩陣
};
window.addEventListener('keydown', function (event) {
  switch (event.key) {
    case 'ArrowLeft':  // 按左箭頭鍵
      moveLeft();
      break;
    case 'ArrowRight': // 按右箭頭鍵
      moveRight();
      break;
  }
});
// 交互事件
addEventListener('dblclick', onMouseDblclick, false)
function onMouseDblclick(event) {
  console.log("event")
  let intersects = getIntersects(event);
  if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {
    const selectedObject = intersects[0].object;
    let selectedObjects = [];
    selectedObjects.push(selectedObject);
    console.log(selectedObjects)
    // outlinePass.selectedObjects = selectedObjects;
  }
}
function moveLeft() {
  if (glbModel) {
    glbModel.position.x -= 10; // 向左移動10單位
  }
}
function moveRight() {
  if (glbModel) {
    glbModel.position.x += 10; // 向右移動10單位
  }
}
//獲取與射線相交的對象數(shù)組
function getIntersects(event) {
  let rayCaster = new THREE.Raycaster();
  let mouse = new THREE.Vector2();
  //通過鼠標點擊位置,計算出raycaster所需點的位置,以屏幕為中心點,范圍-1到1
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; //這里為什么是-號,沒有就無法點中
  //通過鼠標點擊的位置(二維坐標)和當前相機的矩陣計算出射線位置
  rayCaster.setFromCamera(mouse, camera);
  return rayCaster.intersectObjects(scene.children);
}
</script>
<style>
.workshop-text {}
.workshop-text p {
  font-size: 0.9rem;
  font-weight: bold;
  padding: 10px;
  color: #0ff;
}
#tag {
  padding: 0px 10px;
  border: #00ffff solid 1px;
  height: 40px;
  border-radius: 5px;
  width: 65px;
}
</style>

效果:

到此這篇關于在Three.js中使用CSS3DRenderer和CSS3DSprite實現(xiàn)模型標簽文字的文章就介紹到這了,更多相關Three.js模型標簽文字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript節(jié)點及列表操作實例小結

    JavaScript節(jié)點及列表操作實例小結

    這篇文章主要介紹了JavaScript節(jié)點及列表操作的方法,以實例的形式較為詳細的總結了javascript針對節(jié)點操作的相關技巧,并給出了一個完整的節(jié)點操作方法實例總結,需要的朋友可以參考下
    2015-08-08
  • JavaScript函數(shù)及其prototype詳解

    JavaScript函數(shù)及其prototype詳解

    這篇文章主要介紹了JavaScript函數(shù)及其prototype詳解的相關資料,需要的朋友可以參考下
    2023-03-03
  • echarts自定義tooltip中的內(nèi)容代碼示例

    echarts自定義tooltip中的內(nèi)容代碼示例

    在ECharts中,通過formatter函數(shù)自定義圖例樣式,可以實現(xiàn)更靈活的圖表展示,滿足特定的視覺需求,這篇文章主要介紹了echarts自定義tooltip中內(nèi)容的相關資料,需要的朋友可以參考下
    2024-10-10
  • ES6教程之for循環(huán)和Map,Set用法分析

    ES6教程之for循環(huán)和Map,Set用法分析

    這篇文章主要介紹了ES6教程之for循環(huán)和Map,Set用法,結合實例形式分析了ECMAScript6中for循環(huán)和Map,Set基本概念、功能、使用方法與相關注意事項,需要的朋友可以參考下
    2017-04-04
  • uni-app動態(tài)修改主題色的方法詳解

    uni-app動態(tài)修改主題色的方法詳解

    最近在看uniapp開發(fā)app時需要實現(xiàn)動態(tài)修改主題色的功能,這篇文章主要給大家介紹了關于uni-app動態(tài)修改主題色的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-12-12
  • ES6新增數(shù)據(jù)結構WeakSet的用法詳解

    ES6新增數(shù)據(jù)結構WeakSet的用法詳解

    WeakSet和Set類似,同樣是元素不重復的集合,它們的區(qū)別是WeakSet內(nèi)的元素必須是對象,不能是其它類型。接下來通過本文給大家詳細介紹ES6新增數(shù)據(jù)結構WeakSet的用法,感興趣的朋友一起看看吧
    2017-08-08
  • JavaScript實現(xiàn)百度搜索框效果

    JavaScript實現(xiàn)百度搜索框效果

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)百度搜索框效果
    ,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • JS實現(xiàn)websocket長輪詢實時消息提示的效果

    JS實現(xiàn)websocket長輪詢實時消息提示的效果

    這篇文章主要介紹了JS實現(xiàn)websocket長輪詢實時消息提示的效果的相關資料,需要的朋友可以參考下
    2017-10-10
  • 跟我學習javascript的基本類型和引用類型

    跟我學習javascript的基本類型和引用類型

    跟我學習javascript的基本類型和引用類型,利用圖解的方式,告訴大家javascript的基本類型和引用類型的區(qū)別和聯(lián)系,感興趣的小伙伴們可以參考一下
    2015-11-11
  • JS實現(xiàn)網(wǎng)頁頂部向下滑出的全國城市切換導航效果

    JS實現(xiàn)網(wǎng)頁頂部向下滑出的全國城市切換導航效果

    這篇文章主要介紹了JS實現(xiàn)網(wǎng)頁頂部向下滑出的全國城市切換導航效果,涉及javascript鼠標事件及頁面元素顯示的實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08

最新評論

宁化县| 华池县| 龙井市| 永德县| 秦皇岛市| 松江区| 无锡市| 霍山县| 通化市| 开原市| 乡宁县| 察哈| 措勤县| 岚皋县| 富平县| 华池县| 湖南省| 绥棱县| 西宁市| 海南省| 嵊泗县| 辽阳市| 布拖县| 光泽县| 惠来县| 额济纳旗| 柞水县| 镇江市| 刚察县| 黄山市| 广宁县| 安新县| 册亨县| 讷河市| 武胜县| 长治县| 雷波县| 元江| 凤阳县| 汉寿县| 吴桥县|