<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - box selection</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: #f0f0f0; color: #000; touch-action: none; } a { color: #08e; } .selectBox { border: 1px solid #55aaff; background-color: rgba(75, 160, 255, 0.3); position: fixed; } </style> </head> <body> <div id="info"> <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - box selection </div> <!-- Import maps polyfill --> <!-- Remove this when import maps will be widely supported --> <script async src="https://unpkg.com/es-module-shims@1.8.0/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "../build/three.module.js", "three/addons/": "./jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import Stats from 'three/addons/libs/stats.module.js'; import { SelectionBox } from 'three/addons/interactive/SelectionBox.js'; import { SelectionHelper } from 'three/addons/interactive/SelectionHelper.js'; let container, stats; let camera, scene, renderer; init(); animate(); function init() { container = document.createElement( 'div' ); document.body.appendChild( container ); camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 500 ); camera.position.z = 50; scene = new THREE.Scene(); scene.background = new THREE.Color( 0xf0f0f0 ); scene.add( new THREE.AmbientLight( 0xaaaaaa ) ); const light = new THREE.SpotLight( 0xffffff, 10000 ); light.position.set( 0, 25, 50 ); light.angle = Math.PI / 5; light.castShadow = true; light.shadow.camera.near = 10; light.shadow.camera.far = 100; light.shadow.mapSize.width = 1024; light.shadow.mapSize.height = 1024; scene.add( light ); const geometry = new THREE.BoxGeometry(); for ( let i = 0; i < 200; i ++ ) { const object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) ); object.position.x = Math.random() * 80 - 40; object.position.y = Math.random() * 45 - 25; object.position.z = Math.random() * 45 - 25; object.rotation.x = Math.random() * 2 * Math.PI; object.rotation.y = Math.random() * 2 * Math.PI; object.rotation.z = Math.random() * 2 * Math.PI; object.scale.x = Math.random() * 2 + 1; object.scale.y = Math.random() * 2 + 1; object.scale.z = Math.random() * 2 + 1; object.castShadow = true; object.receiveShadow = true; scene.add( object ); } renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFShadowMap; container.appendChild( renderer.domElement ); stats = new Stats(); container.appendChild( stats.dom ); window.addEventListener( 'resize', onWindowResize ); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { renderer.render( scene, camera ); } const selectionBox = new SelectionBox( camera, scene ); const helper = new SelectionHelper( renderer, 'selectBox' ); document.addEventListener( 'pointerdown', function ( event ) { for ( const item of selectionBox.collection ) { item.material.emissive.set( 0x000000 ); } selectionBox.startPoint.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); } ); document.addEventListener( 'pointermove', function ( event ) { if ( helper.isDown ) { for ( let i = 0; i < selectionBox.collection.length; i ++ ) { selectionBox.collection[ i ].material.emissive.set( 0x000000 ); } selectionBox.endPoint.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); const allSelected = selectionBox.select(); for ( let i = 0; i < allSelected.length; i ++ ) { allSelected[ i ].material.emissive.set( 0xffffff ); } } } ); document.addEventListener( 'pointerup', function ( event ) { selectionBox.endPoint.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); const allSelected = selectionBox.select(); for ( let i = 0; i < allSelected.length; i ++ ) { allSelected[ i ].material.emissive.set( 0xffffff ); } } ); </script> </body> </html>