介紹,實現場景中物體標注標簽信息)
系列文章目錄Three.js 快速入門教程【一】開啟你的 3D Web 開發之旅Three.js 快速入門教程【二】透視投影相機Three.js 快速入門教程【三】渲染器Three.js 快速入門教程【四】三維坐標系Three.js 快速入門教程【五】動畫渲染循環Three.js 快速入門教程【六】相機控件 OrbitControlsThree.js 快速入門教程【七】常見幾何體類型Three.js 快速入門教程【八】常見材質類型Three.js 快速入門教程【九】光源類型Three.js 快速入門教程【十】常見的紋理類型Three.js 快速入門教程【十一】天空盒的多種實現方式Three.js 快速入門教程【十二】外部模型加載Three.js 快速入門教程【十三】外部模型加載后常見的處理操作Three.js 快速入門教程【十四】使用Stats.js監控渲染幀率和性能優化Three.js 快速入門教程【十五】交互神器DragControls使用詳解實現對物體或模型拖拽Three.js 快速入門教程【十六】調試神器 gui.js使用詳解可視化面板控制場景參數提高開發效率Three.js 快速入門教程【十七】射線拾取模型——射線與射線投射器Raycaster介紹Three.js 快速入門教程【十八】射線拾取模型——鼠標點擊屏幕選中模型或物體Three.js 快速入門教程【十九】CSS2D渲染器介紹實現場景中物體或設備標注標簽信息Three.js 快速入門教程【二十】三維模型優化實戰使用gltf-pipeline與Draco對模型進行壓縮提高加載速度和流暢性文章目錄系列文章目錄一、前言二、CSS3DRendererCSS3D渲染器介紹三、CSS3DRenderer 和 CSS2DRenderer區別1. 變換支持2. 視覺效果3. 性能4. 使用場景5. 代碼對比四、CSS3DObjectCSS3D對象模型五、示例代碼五、CSS3DSprite CSS3D精靈模型三種渲染方式簡單總結六、總結一、前言在 Three.js 中構建 3D 場景時經常需要為場景中的設備或對象添加標簽標注以提供更多的信息。在前面系列文章Three.js 快速入門教程【十九】CSS2DRendererCSS2D渲染器一文中介紹了通過CSS2DRenderer來渲染標簽該方式有其弊端例如標簽始終保持原來大小無法跟隨相機縮放。這個時候我們需要使用另外一種渲染方式CSS3DRendererCSS3D渲染器來生成標簽。本文將講解如何使用CSS3DRenderer來渲染標簽以及和CSS2DRenderer區別。二、CSS3DRendererCSS3D渲染器介紹CSS3DRenderer 是 Three.js 提供的一種渲染器它不使用 WebGL 繪制 3D 場景而是通過 CSS 3D 變換來渲染 HTML 元素。這意味著你可以在 3D 空間中放置普通的 HTML 內容如文本、圖片、按鈕等并利用 Three.js 的強大功能控制它們的位置、旋轉和動畫。CSS3DRenderer用法和CSS2DRenderer整體使用流程基本相同配合CSS3模型 CSS3DObject或CSS3DSprite生成標簽。三、CSS3DRenderer 和 CSS2DRenderer區別1. 變換支持CSS3DRenderer支持完整的 3D 變換平移、旋轉、縮放元素可集成到三維空間中跟隨相機視角產生透視效果如近大遠小、遮擋關系。CSS2DRenderer僅支持 2D 變換平面平移、旋轉元素始終面向屏幕無透視變形。2. 視覺效果CSS3DRenderer元素會隨 3D 場景的視角變化而動態變形例如貼在立方體表面的 HTML 內容在旋轉時會有正確的 3D 效果。CSS2DRenderer元素始終平鋪在屏幕上僅位置跟隨 3D 對象但保持固定方向和比例類似 HUD 標簽。3. 性能CSS3DRenderer由于復雜的 3D 矩陣計算和瀏覽器渲染開銷性能較低尤其在元素數量多時。CSS2DRenderer僅處理 2D 變換性能更高適合需要頻繁更新的場景。4. 使用場景CSS3DRenderer適用于需要 HTML 元素深度融入 3D 空間的場景如 3D 數據可視化、復雜 UI如可交互的 3D 面板。CSS2DRenderer適合靜態標簽、信息提示如地圖標記、物體名稱需跟隨 3D 對象位置但無需透視變形。5. 代碼對比代碼使用流程基本相同把名稱由2D換3D即可例如// CSS3DRendererconstcss3DRenderernewCSS3DRenderer();constcss3DObjectnewCSS3DObject(divElement);css3DObject.position.set(10,20,30);// 三維坐標css3DObject.rotation.xMath.PI/2;// 支持繞 X/Y/Z 軸旋轉css3Renderer.render(scene,camera);// CSS2DRendererconstcss2DRenderernewCSS2DRenderer();constcss2DObjectnewCSS2DObject(divElement);css2DObject.position.set(10,20);// 僅 X/Y 坐標Z 軸用于遮擋排序不影響位置css2DObject.rotation.zMath.PI/4;// 僅繞 Z 軸旋轉類似屏幕平面旋轉css2Renderer.render(scene,camera);//渲染四、CSS3DObjectCSS3D對象模型CSS3DObject 與CSS2DObject作用和用法類似是一個特殊的對象允許你將 HTML/CSS 元素集成到 3D 場景中并通過 CSS3D 變換實現 3D 效果。它屬于 CSS3DRenderer 的一部分與傳統的 WebGL 渲染器如 WebGLRenderer不同主要用于混合 HTML 內容和 3D 場景創建 CSS3DObject// 創建一個 HTML 元素constelementdocument.createElement(div);element.innerHTMLHello CSS3D!;element.style.backgroundColor#f00;element.style.padding20px;// 轉換為 CSS3DObjectconstcss3DObjectnewTHREE.CSS3DObject(element);// 像普通 3D 對象一樣設置位置、旋轉、縮放css3DObject.position.set(0,0,0);css3DObject.rotation.yMath.PI/4;scene.add(css3DObject);通過CSS3DRenderer渲染CSS3DObject 需要與 CSS3DRenderer 配合使用而非 WebGLRendererconstcss3DRenderernewTHREE.CSS3DRenderer();css3DRenderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(css3DRenderer.domElement);// 在動畫循環中渲染functionanimate(){css3DRenderer.render(scene,camera);requestAnimationFrame(animate);}animate();五、示例代碼下面展示一個正方體和圓柱體分別在頭頂標注標簽示例import*asTHREEfromthree;import{OrbitControls}fromthree/addons/controls/OrbitControls.js;// 引入CSS3渲染器CSS3DRenderer和CSS3模型對象CSS3DObjectimport{CSS3DRenderer,CSS3DObject}fromthree/addons/renderers/CSS3DRenderer.js;// 創建場景constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x333333);//坐標輔助線constaxesHelpernewTHREE.AxesHelper(500);scene.add(axesHelper);// 創建相機constcameranewTHREE.PerspectiveCamera(// 透視相機75,window.innerWidth/window.innerHeight,0.1,3000);camera.position.set(2,5,10);// 創建WebGLRenderer渲染器constrenderernewTHREE.WebGLRenderer();// 設置渲染器寬高renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);//加入點光源letpointLightnewTHREE.PointLight(0xffffff,15,1000,1);pointLight.position.set(3,3,3);scene.add(pointLight);/** * 創建一個立方體標簽 */constboxGeometrynewTHREE.BoxGeometry(1,1,1);constboxMaterialnewTHREE.MeshLambertMaterial({color:0x1678e2});constboxMeshnewTHREE.Mesh(boxGeometry,boxMaterial);//設置立方體位置boxMesh.position.set(2,2,2);scene.add(boxMesh);// 創建一個 HTML 元素作為標簽constlabelElementcreateLabelElement(立方體);// 創建 CSS3DObject 并將標簽元素添加到其中constlabelnewCSS3DObject(labelElement);// 設置標簽相對于設備對象的位置label.position.set(0,1,0);//縮放標簽label.scale.set(0.015,0.015,0.015);//標簽添加到立方體boxMesh.add(label);/** * 創建一個圓柱體標簽 */constgeometrynewTHREE.CylinderGeometry(1,1,1,32);//創建材質constmaterialnewTHREE.MeshLambertMaterial({color:0xffff00});// 創建一個網格對象將幾何體和材質組合在一起constcylinderMeshnewTHREE.Mesh(geometry,material);//設置圓柱體體位置cylinderMesh.position.set(5,2,2);//添加到場景中scene.add(cylinderMesh);// 創建一個 HTML 元素作為標簽constlabelElement2createLabelElement(圓柱體);// 創建 CSS3DObject 并將標簽元素添加到其中constlabel2newCSS3DObject(labelElement2);// 設置標簽相對于設備對象的位置label2.position.set(0,1,0);//縮放標簽label2.scale.set(0.015,0.015,0.015);//標簽添加到圓柱體cylinderMesh.add(label2);//創建一個CSS3渲染器constcss3RenderernewCSS3DRenderer();css3Renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(css3Renderer.domElement);css3Renderer.domElement.style.positionabsolute;css3Renderer.domElement.style.top0;css3Renderer.domElement.style.pointerEventsnone;//創建標簽DomfunctioncreateLabelElement(text){constlabelElementdocument.createElement(div);labelElement.textContenttext;labelElement.style.backgroundColorwhite;labelElement.style.padding5px;labelElement.style.border1px solid black;labelElement.style.borderRadius5px;returnlabelElement;}// 控制器constcontrolnewOrbitControls(camera,renderer.domElement);// 渲染循環動畫functionanimate(){requestAnimationFrame(animate);control.update();renderer.render(scene,camera);css3Renderer.render(scene,camera);}// 執行動畫animate()運行效果五、CSS3DSprite CSS3D精靈模型CSS3DSprite 屬于 CSS3DObject 的特殊類型它具備自動朝向相機的功能這一點和 THREE.Sprite精靈模型 類似無論相機處于何種位置元素始終面向觀察者。除了這一點其他和CSS3DObject 渲染規律一樣使用方式也相同。當一些特殊場景要求標簽始終要面向攝像頭就可以使用CSS3D精靈模型。把上述示例代碼CSS3DObject 換成CSS3DSprite 觀察效果import*asTHREEfromthree;import{OrbitControls}fromthree/addons/controls/OrbitControls.js;// 引入CSS3渲染器CSS3DRenderer和CSS3模型對象CSS3DObjectimport{CSS3DRenderer,CSS3DObject,CSS3DSprite}fromthree/addons/renderers/CSS3DRenderer.js;// 創建場景constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x333333);//坐標輔助線constaxesHelpernewTHREE.AxesHelper(500);scene.add(axesHelper);// 創建相機constcameranewTHREE.PerspectiveCamera(// 透視相機75,// 視角 角度數window.innerWidth/window.innerHeight,// 寬高比 占據屏幕0.1,// 近平面相機最近能看到物體3000// 遠平面相機最遠能看到物體);camera.position.set(2,5,10);// 創建WebGLRenderer渲染器constrenderernewTHREE.WebGLRenderer();// 設置渲染器寬高renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);//加入點光源letpointLightnewTHREE.PointLight(0xffffff,15,1000,1);pointLight.position.set(3,3,3);scene.add(pointLight);/** * 創建一個立方體標簽 */constboxGeometrynewTHREE.BoxGeometry(1,1,1);constboxMaterialnewTHREE.MeshLambertMaterial({color:0x1678e2});constboxMeshnewTHREE.Mesh(boxGeometry,boxMaterial);//設置立方體位置boxMesh.position.set(2,2,2);scene.add(boxMesh);// 創建一個 HTML 元素作為標簽constlabelElementcreateLabelElement(立方體);// 創建 CSS3DSprite 并將標簽元素添加到其中constlabelnewCSS3DSprite(labelElement);// 設置標簽相對于設備對象的位置label.position.set(0,1,0);//縮放標簽label.scale.set(0.015,0.015,0.015);//標簽添加到立方體boxMesh.add(label);/** * 創建一個圓柱體標簽 */constgeometrynewTHREE.CylinderGeometry(1,1,1,32);//創建材質constmaterialnewTHREE.MeshLambertMaterial({color:0xffff00});// 創建一個網格對象將幾何體和材質組合在一起constcylinderMeshnewTHREE.Mesh(geometry,material);//設置圓柱體體位置cylinderMesh.position.set(5,2,2);//添加到場景中scene.add(cylinderMesh);// 創建一個 HTML 元素作為標簽constlabelElement2createLabelElement(圓柱體);// 創建 CSS3DSprite 并將標簽元素添加到其中constlabel2newCSS3DSprite(labelElement2);// 設置標簽相對于設備對象的位置label2.position.set(0,1,0);//縮放標簽label2.scale.set(0.015,0.015,0.015);//標簽添加到圓柱體cylinderMesh.add(label2);//創建一個CSS3渲染器constcss3RenderernewCSS3DRenderer();css3Renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(css3Renderer.domElement);css3Renderer.domElement.style.positionabsolute;css3Renderer.domElement.style.top0;css3Renderer.domElement.style.pointerEventsnone;//創建標簽DomfunctioncreateLabelElement(text){constlabelElementdocument.createElement(div);labelElement.textContenttext;labelElement.style.backgroundColorwhite;labelElement.style.padding5px;labelElement.style.border1px solid black;labelElement.style.borderRadius5px;returnlabelElement;}// 控制器constcontrolnewOrbitControls(camera,renderer.domElement);// 渲染循環動畫functionanimate(){requestAnimationFrame(animate);control.update();renderer.render(scene,camera);css3Renderer.render(scene,camera);}// 執行動畫animate()運行效果從運行效果可以發現CSS3DSprite在保持CSS3DObject原有渲染特點如可縮放基礎上改變面向方向使得標簽始終面向攝像頭 。三種渲染方式簡單總結CSS2DRenderer :標簽不能縮放、默認始終面向攝像頭只能在2D平面通過代碼控制方向CSS3DObject :標簽能縮放、默認保持初始方向可在3D平面通過代碼控制方向CSS3DSprite :標簽能縮放、默認始終面向攝像頭可在3D平面通過代碼控制方向六、總結通過本篇文章我們介紹了在 Three.js 中使用 CSS3DRenderer 渲染標簽方法以及和CSS2DRenderer對比。實際開發中應根據具體使用場景選擇合理的渲染方式來滿足需求。更多three.js入門知識點請關注該系列教程后續的更新。