css3d_mixed.html 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>three.js css3d - mixed</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <link type="text/css" rel="stylesheet" href="main.css">
  8. <style>
  9. body {
  10. background-color: #ffffff;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <script type="importmap">
  16. {
  17. "imports": {
  18. "three": "../build/three.module.js",
  19. "three/addons/": "./jsm/"
  20. }
  21. }
  22. </script>
  23. <script type="module">
  24. import * as THREE from 'three';
  25. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  26. import { CSS3DRenderer, CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
  27. let camera, scene, rendererCSS3D, rendererWebGL;
  28. let controls;
  29. init();
  30. function init() {
  31. rendererCSS3D = new CSS3DRenderer();
  32. rendererCSS3D.setSize( window.innerWidth, window.innerHeight );
  33. document.body.appendChild( rendererCSS3D.domElement );
  34. rendererWebGL = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
  35. rendererWebGL.domElement.style.position = 'absolute';
  36. rendererWebGL.domElement.style.top = '0';
  37. rendererWebGL.setPixelRatio( window.devicePixelRatio );
  38. rendererWebGL.setSize( window.innerWidth, window.innerHeight );
  39. rendererWebGL.toneMapping = THREE.NeutralToneMapping;
  40. rendererWebGL.setAnimationLoop( animate );
  41. document.body.appendChild( rendererWebGL.domElement );
  42. camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
  43. camera.position.set( - 1000, 500, 1500 );
  44. scene = new THREE.Scene();
  45. scene.background = new THREE.Color( 0xf0f0f0 );
  46. // Add room
  47. const roomGeometry = new THREE.EdgesGeometry( new THREE.BoxGeometry( 4000, 2000, 4000, 10, 5, 10 ) );
  48. const roomMaterial = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2, transparent: true } );
  49. const room = new THREE.LineSegments( roomGeometry, roomMaterial );
  50. scene.add( room );
  51. // Add light
  52. const hemisphereLight = new THREE.HemisphereLight( 0xffffff, 0x444444, 4 );
  53. hemisphereLight.position.set( - 25, 100, 50 );
  54. scene.add( hemisphereLight );
  55. // Add cutout mesh
  56. const geometry = new THREE.PlaneGeometry( 1024, 768 );
  57. const material = new THREE.MeshBasicMaterial( {
  58. color: 0xff0000,
  59. blending: THREE.NoBlending,
  60. opacity: 0,
  61. premultipliedAlpha: true
  62. } );
  63. const mesh = new THREE.Mesh( geometry, material );
  64. mesh.name = 'cutout';
  65. scene.add( mesh );
  66. // Add frame
  67. const frame = buildFrame( 1024, 768, 50 );
  68. scene.add( frame );
  69. // Add CSS3D element
  70. const iframe = document.createElement( 'iframe' );
  71. iframe.style.width = '1028px';
  72. iframe.style.height = '768px';
  73. iframe.style.border = '0px';
  74. iframe.src = './#webgl_animation_keyframes';
  75. scene.add( new CSS3DObject( iframe ) );
  76. // Add controls
  77. controls = new OrbitControls( camera );
  78. controls.connect( rendererWebGL.domElement );
  79. controls.enableDamping = true;
  80. // Track OrbitControls state
  81. let isDragging = false;
  82. controls.addEventListener( 'start', () => isDragging = true );
  83. controls.addEventListener( 'end', () => isDragging = false );
  84. // raycast to find CSS3DObject
  85. const raycaster = new THREE.Raycaster();
  86. const pointer = new THREE.Vector2();
  87. document.addEventListener( 'pointermove', ( event ) => {
  88. // Skip raycasting when dragging
  89. if ( isDragging ) return;
  90. pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  91. pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  92. raycaster.setFromCamera( pointer, camera );
  93. const intersects = raycaster.intersectObjects( scene.children, true );
  94. rendererWebGL.domElement.style.pointerEvents = '';
  95. if ( intersects.length > 0 ) {
  96. const object = intersects[ 0 ].object;
  97. if ( object.name === 'cutout' ) {
  98. rendererWebGL.domElement.style.pointerEvents = 'none';
  99. }
  100. }
  101. } );
  102. window.addEventListener( 'resize', onWindowResize );
  103. }
  104. function buildFrame( width, height, thickness ) {
  105. const group = new THREE.Group();
  106. const material = new THREE.MeshStandardMaterial( { color: 0x2200ff } );
  107. // Create the frame border
  108. const outerShape = new THREE.Shape();
  109. outerShape.moveTo( - ( width / 2 + thickness ), - ( height / 2 + thickness ) );
  110. outerShape.lineTo( width / 2 + thickness, - ( height / 2 + thickness ) );
  111. outerShape.lineTo( width / 2 + thickness, height / 2 + thickness );
  112. outerShape.lineTo( - ( width / 2 + thickness ), height / 2 + thickness );
  113. outerShape.lineTo( - ( width / 2 + thickness ), - ( height / 2 + thickness ) );
  114. // Create inner rectangle (hole)
  115. const innerHole = new THREE.Path();
  116. innerHole.moveTo( - width / 2, - height / 2 );
  117. innerHole.lineTo( width / 2, - height / 2 );
  118. innerHole.lineTo( width / 2, height / 2 );
  119. innerHole.lineTo( - width / 2, height / 2 );
  120. innerHole.lineTo( - width / 2, - height / 2 );
  121. outerShape.holes.push( innerHole );
  122. const frameGeometry = new THREE.ExtrudeGeometry( outerShape, {
  123. depth: thickness,
  124. bevelEnabled: false
  125. } );
  126. const frameMesh = new THREE.Mesh( frameGeometry, material );
  127. frameMesh.position.z = - thickness / 2;
  128. group.add( frameMesh );
  129. // Add back plane
  130. const backGeometry = new THREE.PlaneGeometry( width + ( thickness * 2 ), height + ( thickness * 2 ) );
  131. const backMesh = new THREE.Mesh( backGeometry, material );
  132. backMesh.position.set( 0, 0, - thickness / 2 );
  133. backMesh.rotation.y = Math.PI;
  134. group.add( backMesh );
  135. return group;
  136. }
  137. function onWindowResize() {
  138. camera.aspect = window.innerWidth / window.innerHeight;
  139. camera.updateProjectionMatrix();
  140. rendererWebGL.setSize( window.innerWidth, window.innerHeight );
  141. rendererCSS3D.setSize( window.innerWidth, window.innerHeight );
  142. }
  143. function animate() {
  144. controls.update();
  145. rendererWebGL.render( scene, camera );
  146. rendererCSS3D.render( scene, camera );
  147. }
  148. </script>
  149. </body>
  150. </html>
粤ICP备19079148号