如何为CSS2DRenderer添加重置函数清除已渲染的CSS2DObject?
如何实现CSS2DRenderer的重置功能以移除所有CSS2DObject
问题描述
我使用以下Three.js类创建场景、相机、渲染器及CSS2DRenderer,希望添加一个重置函数(删除并重新添加CSS2DRenderer)以移除所有之前渲染的CSS2DObject,请问该如何正确实现?
import { Scene, Color, Vector3, AxesHelper, PerspectiveCamera, WebGLRenderer, DirectionalLight, HemisphereLight, AmbientLight, sRGBEncoding } from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js"; // import Stats from 'three/examples/jsm/libs/stats.module.js'; export default class SceneCreator { /** * * @param {*} container */ constructor(container) { this.container = container; this.scene = null; this.camera = null; this.renderer = null; this.css_renderer = new CSS2DRenderer(); this.controls = null; // 新增:存储OrbitControls实例 // this.stats = new Stats(); this.initScene(); }; initScene=()=> { this.scene = new Scene(); this.scene.background = new Color(0x21252d); this.createCamera(); this.createLights(); this.createControls(); this.createRenderer(); this.createAxe(); // this.container.appendChild(this.stats.dom); this.renderer.setAnimationLoop(() => { this.renderer.render(this.scene, this.camera); this.css_renderer.render(this.scene, this.camera); // this.stats.update(); }); this.css_renderer.setSize( this.container.clientWidth, this.container.clientHeight ); this.css_renderer.domElement.style.position = 'absolute'; this.css_renderer.domElement.style.top = '0px'; this.container.appendChild(this.css_renderer.domElement); window.addEventListener("resize", this.onWindowResize, false); } createCamera=()=> { const fov = 60; const near = 1; const far = 1000; const aspect_ratio = this.container.clientWidth/this.container.clientHeight this.camera = new PerspectiveCamera(fov, aspect_ratio, near, far); this.camera.position.set(0.1, 10, 10); this.camera.lookAt(0, 0, 0); } createControls=()=> { /* Create Controls to allow for scene control */ // const controls = new OrbitControls(this.camera, this.container); this.controls = new OrbitControls( this.camera, this.css_renderer.domElement ); // 修改:将controls存储为实例属性 this.controls.update(); } createLights= ()=> { const mainLight = new DirectionalLight(0xffffff, 5); mainLight.position.set(10, 10, 10); const hemisphereLight = new HemisphereLight(0xddeeff, 0x202020, 5); const ambientLight = new AmbientLight(0x404040, 5); this.scene.add(mainLight, hemisphereLight, ambientLight); } createAxe = (len=1.6, pos=null) => { const axis = new AxesHelper(len); const red = new Color(0xff0000); const green = new Color(0x00ff00); const blue = new Color(0x0000ff); axis.setColors(green, blue, red); if (pos === null) { pos = new Vector3(8.0, 5.0, -3.2); } axis.position.x = pos.x; axis.position.y = pos.y; axis.position.z = pos.z; this.scene.add(axis); } createRenderer = ()=> { this.renderer = new WebGLRenderer('webgl2',{ antialias: true, alpha: true }); this.renderer.setClearColor( 0xA3A3A3, 0 ); this.renderer.setSize(this.container.clientWidth, this.container.clientHeight); this.renderer.setPixelRatio(window.devicePixelRatio); this.renderer.physicallyCorrectLights = true; this.renderer.outputEncoding = sRGBEncoding; this.container.appendChild(this.renderer.domElement); } onWindowResize = ()=> { this.camera.aspect = this.container.clientWidth / this.container.clientHeight; // Update camera frustum this.camera.updateProjectionMatrix(); this.renderer.setSize(this.container.clientWidth, this.container.clientHeight); this.css_renderer.setSize(this.container.clientWidth, this.container.clientHeight); } // 新增:重置CSS2DRenderer的方法 resetCSSRenderer = () => { // 1. 移除旧的CSS渲染器DOM元素 if (this.css_renderer?.domElement.parentNode) { this.css_renderer.domElement.parentNode.removeChild(this.css_renderer.domElement); } // 2. 销毁旧渲染器,释放资源 if (this.css_renderer) { this.css_renderer.dispose(); } // 3. 创建并初始化新的CSS2DRenderer this.css_renderer = new CSS2DRenderer(); this.css_renderer.setSize(this.container.clientWidth, this.container.clientHeight); this.css_renderer.domElement.style.position = 'absolute'; this.css_renderer.domElement.style.top = '0px'; this.container.appendChild(this.css_renderer.domElement); // 4. 更新轨道控制器的绑定元素 if (this.controls) { this.controls.domElement = this.css_renderer.domElement; } // 5. 清理场景中所有CSS2DObject(可选但推荐) this.scene.children = this.scene.children.filter(child => !child.isCSS2DObject); } getScene = () => { return this.scene; } getCamera = () => { return this.camera; } getRenderer = () => { return this.renderer; } getCSS2DRenderer = () => { return this.css_renderer; } }
关键说明
- 存储OrbitControls实例:将
controls改为实例属性this.controls,以便重置时更新其绑定的DOM元素,避免控制器失效。 - 完整清理旧渲染器:不仅移除DOM元素,还调用
dispose()方法释放内部资源,防止内存泄漏。 - 场景对象清理:通过过滤场景子元素,移除所有
isCSS2DObject标记的对象,确保新渲染器不会渲染旧内容。 - 同步控制器绑定:更新
this.controls.domElement为新的CSS渲染器DOM元素,保证轨道控制正常工作。
使用时直接调用sceneCreatorInstance.resetCSSRenderer()即可完成重置。
内容的提问来源于stack exchange,提问作者Bilal
相关产品推荐
相关产品推荐

