瀏覽代碼

Update HTMLMesh to observe DOM mutation and support Canvas elements (#23386)

* Update HTMLMesh to observe DOM mutation and support Canvas elements

- enable html2canvas updates to be made automatically based on dom updates
- also add Stats.js to VR Sandbox

* Switch raf to setTimeout in HTMLMesh, also fix repeat notes in haptics
Joshua Koo 3 年之前
父節點
當前提交
91658c9725
共有 3 個文件被更改,包括 71 次插入3 次删除
  1. 49 2
      examples/jsm/interactive/HTMLMesh.js
  2. 1 1
      examples/webxr_vr_haptics.html
  3. 21 0
      examples/webxr_vr_sandbox.html

+ 49 - 2
examples/jsm/interactive/HTMLMesh.js

@@ -60,13 +60,32 @@ class HTMLTexture extends CanvasTexture {
 		this.minFilter = LinearFilter;
 		this.magFilter = LinearFilter;
 
+		// Create an observer on the DOM, and run html2canvas update in the next loop
+		const observer = new MutationObserver( () => {
+
+			if ( ! this.scheduleUpdate ) {
+
+				// ideally should use xr.requestAnimationFrame, here setTimeout to avoid passing the renderer
+				this.scheduleUpdate = setTimeout( () => this.update(), 16 );
+
+			}
+
+		} );
+
+		const config = { attributes: true, childList: true, subtree: true, characterData: true };
+		observer.observe( dom, config );
+
+		this.observer = observer;
+
 	}
 
 	dispatchDOMEvent( event ) {
 
-		htmlevent( this.dom, event.type, event.data.x, event.data.y );
+		if ( event.data ) {
+
+			htmlevent( this.dom, event.type, event.data.x, event.data.y );
 
-		this.update();
+		}
 
 	}
 
@@ -75,10 +94,27 @@ class HTMLTexture extends CanvasTexture {
 		this.image = html2canvas( this.dom );
 		this.needsUpdate = true;
 
+		this.scheduleUpdate = null;
+
+	}
+
+	dispose() {
+
+		if ( this.observer ) {
+
+			this.observer.disconnect();
+
+		}
+
+		this.scheduleUpdate = clearTimeout( this.scheduleUpdate );
+
+		super.dispose();
+
 	}
 
 }
 
+
 //
 
 const canvases = new WeakMap();
@@ -202,6 +238,17 @@ function html2canvas( element ) {
 
 			drawText( style, x, y, element.nodeValue.trim() );
 
+		} else if ( element instanceof HTMLCanvasElement ) {
+
+			// Canvas element
+			if ( element.style.display === 'none' ) return;
+
+			context.save();
+			const dpr = window.devicePixelRatio;
+			context.scale(1/dpr, 1/dpr);
+			context.drawImage(element, 0, 0 );
+			context.restore();
+
 		} else {
 
 			if ( element.style.display === 'none' ) return;

+ 1 - 1
examples/webxr_vr_haptics.html

@@ -43,7 +43,7 @@
 			let audioCtx = null;
 
 			// minor pentatonic scale, so whichever notes is striked would be more pleasant
-			const musicScale = [ 0, 3, 5, 7, 10, 12 ];
+			const musicScale = [ 0, 3, 5, 7, 10 ];
 
 			init();
 			animate();

+ 21 - 0
examples/webxr_vr_sandbox.html

@@ -33,9 +33,11 @@
 			import { XRControllerModelFactory } from './jsm/webxr/XRControllerModelFactory.js';
 
 			import { GUI } from './jsm/libs/lil-gui.module.min.js';
+			import Stats from './jsm/libs/stats.module.js';
 
 			let camera, scene, renderer;
 			let reflector;
+			let stats, statsMesh;
 
 			const parameters = {
 				radius: 0.6,
@@ -193,6 +195,21 @@
 				mesh.scale.setScalar( 2 );
 				group.add( mesh );
 
+
+				// Add stats.js
+				stats = new Stats();
+				stats.dom.style.width = '80px';
+				stats.dom.style.height = '48px';
+				document.body.appendChild( stats.dom );
+
+				statsMesh = new HTMLMesh( stats.dom );
+				statsMesh.position.x = - 0.75;
+				statsMesh.position.y = 2;
+				statsMesh.position.z = - 0.6;
+				statsMesh.rotation.y = Math.PI / 4;
+				statsMesh.scale.setScalar( 2.5 );
+				group.add( statsMesh );
+
 			}
 
 			function onWindowResize() {
@@ -218,6 +235,10 @@
 				torus.rotation.y = time * 5;
 
 				renderer.render( scene, camera );
+				stats.update();
+
+				// Canvas elements doesn't trigger DOM updates, so we have to update the texture
+				statsMesh.material.map.update();
 
 			}