Ver Fonte

Added CSS3D + WebGL example. (#31572)

* Added CSS3D + WebGL example.

* Potential fix for code scanning alert no. 3617: Semicolon insertion

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
mrdoob há 4 meses atrás
pai
commit
43849031e1
3 ficheiros alterados com 202 adições e 0 exclusões
  1. 201 0
      examples/css3d_mixed.html
  2. 1 0
      examples/files.json
  3. BIN
      examples/screenshots/css3d_mixed.jpg

+ 201 - 0
examples/css3d_mixed.html

@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>three.js css3d - mixed</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+		<style>
+			body {
+				background-color: #ffffff;
+			}
+		</style>
+	</head>
+	<body>
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.module.js",
+					"three/addons/": "./jsm/"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+			import { CSS3DRenderer, CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
+
+			let camera, scene, rendererCSS3D, rendererWebGL;
+			let controls;
+
+			init();
+
+			function init() {
+
+				rendererCSS3D = new CSS3DRenderer();
+				rendererCSS3D.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( rendererCSS3D.domElement );
+
+				rendererWebGL = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
+				rendererWebGL.domElement.style.position = 'absolute';
+				rendererWebGL.domElement.style.top = '0';
+				rendererWebGL.setPixelRatio( window.devicePixelRatio );
+				rendererWebGL.setSize( window.innerWidth, window.innerHeight );
+				rendererWebGL.toneMapping = THREE.NeutralToneMapping;
+				rendererWebGL.setAnimationLoop( animate );
+				document.body.appendChild( rendererWebGL.domElement );
+
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.set( - 1000, 500, 1500 );
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
+
+				// Add room
+				const roomGeometry = new THREE.EdgesGeometry( new THREE.BoxGeometry( 4000, 2000, 4000, 10, 5, 10 ) );
+				const roomMaterial = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2, transparent: true } );
+				const room = new THREE.LineSegments( roomGeometry, roomMaterial );
+				scene.add( room );
+
+				// Add light
+				const hemisphereLight = new THREE.HemisphereLight( 0xffffff, 0x444444, 4 );
+				hemisphereLight.position.set( - 25, 100, 50 );
+				scene.add( hemisphereLight );
+
+				// Add cutout mesh
+				const geometry = new THREE.PlaneGeometry( 1024, 768 );
+				const material = new THREE.MeshBasicMaterial( {
+					color: 0xff0000,
+					blending: THREE.NoBlending,
+					opacity: 0,
+					premultipliedAlpha: true
+				} );
+				const mesh = new THREE.Mesh( geometry, material );
+				mesh.name = 'cutout';
+				scene.add( mesh );
+
+				// Add frame
+				const frame = buildFrame( 1024, 768, 50 );
+				scene.add( frame );
+
+				// Add CSS3D element
+				const iframe = document.createElement( 'iframe' );
+				iframe.style.width = '1028px';
+				iframe.style.height = '768px';
+				iframe.style.border = '0px';
+				iframe.src = 'https://threejs.org/examples/#webgl_animation_keyframes';
+				scene.add( new CSS3DObject( iframe ) );
+
+				// Add controls
+				controls = new OrbitControls( camera );
+				controls.connect( rendererWebGL.domElement );
+				controls.enableDamping = true;
+
+				// Track OrbitControls state
+				let isDragging = false;
+				controls.addEventListener( 'start', () => isDragging = true );
+				controls.addEventListener( 'end', () => isDragging = false );
+
+				// raycast to find CSS3DObject
+				const raycaster = new THREE.Raycaster();
+				const pointer = new THREE.Vector2();
+				document.addEventListener( 'pointermove', ( event ) => {
+
+					// Skip raycasting when dragging
+					if ( isDragging ) return;
+
+					pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+					pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
+
+					raycaster.setFromCamera( pointer, camera );
+
+					const intersects = raycaster.intersectObjects( scene.children, true );
+
+					rendererWebGL.domElement.style.pointerEvents = '';
+
+					if ( intersects.length > 0 ) {
+
+						const object = intersects[ 0 ].object;
+
+						if ( object.name === 'cutout' ) {
+
+							rendererWebGL.domElement.style.pointerEvents = 'none';
+
+						}
+
+					}
+
+				} );
+
+				window.addEventListener( 'resize', onWindowResize );
+
+			}
+
+			function buildFrame( width, height, thickness ) {
+
+				const group = new THREE.Group();
+				const material = new THREE.MeshStandardMaterial( { color: 0x2200ff } );
+
+				// Create the frame border
+				const outerShape = new THREE.Shape();
+				outerShape.moveTo( - ( width / 2 + thickness ), - ( height / 2 + thickness ) );
+				outerShape.lineTo( width / 2 + thickness, - ( height / 2 + thickness ) );
+				outerShape.lineTo( width / 2 + thickness, height / 2 + thickness );
+				outerShape.lineTo( - ( width / 2 + thickness ), height / 2 + thickness );
+				outerShape.lineTo( - ( width / 2 + thickness ), - ( height / 2 + thickness ) );
+
+				// Create inner rectangle (hole)
+				const innerHole = new THREE.Path();
+				innerHole.moveTo( - width / 2, - height / 2 );
+				innerHole.lineTo( width / 2, - height / 2 );
+				innerHole.lineTo( width / 2, height / 2 );
+				innerHole.lineTo( - width / 2, height / 2 );
+				innerHole.lineTo( - width / 2, - height / 2 );
+
+				outerShape.holes.push( innerHole );
+
+				const frameGeometry = new THREE.ExtrudeGeometry( outerShape, {
+					depth: thickness,
+					bevelEnabled: false
+				} );
+
+				const frameMesh = new THREE.Mesh( frameGeometry, material );
+				frameMesh.position.z = - thickness / 2;
+				group.add( frameMesh );
+
+				// Add back plane
+				const backGeometry = new THREE.PlaneGeometry( width + ( thickness * 2 ), height + ( thickness * 2 ) );
+				const backMesh = new THREE.Mesh( backGeometry, material );
+				backMesh.position.set( 0, 0, - thickness / 2 );
+				backMesh.rotation.y = Math.PI;
+				group.add( backMesh );
+
+				return group;
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				rendererWebGL.setSize( window.innerWidth, window.innerHeight );
+				rendererCSS3D.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				controls.update();
+
+				rendererWebGL.render( scene, camera );
+				rendererCSS3D.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 0
examples/files.json

@@ -554,6 +554,7 @@
 		"css2d_label"
 	],
 	"css3d": [
+		"css3d_mixed",
 		"css3d_molecules",
 		"css3d_orthographic",
 		"css3d_periodictable",

BIN
examples/screenshots/css3d_mixed.jpg


粤ICP备19079148号