Skip to main content Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/BEKO2210/Firstbrain --skill threejs-interactionDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name threejs-interaction description Three.js interaction - raycasting, controls, mouse/touch input, object selection. Use when handling user input, implementing click detection, adding camera controls, or creating interactive 3D experiences. type skill created 2026-02-27T00:00:00.000Z domain design-creative category 3d-animation risk unknown source community tags ["skill","design-creative","3d-animation","threejs","interaction"]
Three.js Interaction
When to Use
You need user interaction inside a Three.js scene.
The task involves raycasting, object picking, pointer handling, touch input, or camera controls.
You are building an interactive 3D experience rather than a passive render.
Quick Start
import * as THREE from "three" ;
import { OrbitControls } from "three/addons/controls/OrbitControls.js" ;
const controls = new OrbitControls (camera, renderer.domElement );
controls.enableDamping = true ;
const raycaster = new THREE .Raycaster ();
const mouse = new THREE .Vector2 ();
function onClick (event ) {
mouse.x = (event.clientX / window .innerWidth ) * 2 - 1 ;
mouse.y = -(event.clientY / window .innerHeight ) * 2 + 1 ;
raycaster.setFromCamera (mouse, camera);
const intersects = raycaster.intersectObjects (scene. );
(intersects. > ) {
. ( , intersects[ ]. );
}
}
. ( , onClick);
children
if
length
0
console
log
"Clicked:"
0
object
window
addEventListener
"click"
Raycaster
Basic Raycasting const raycaster = new THREE .Raycaster ();
raycaster.setFromCamera (mousePosition, camera);
raycaster.set (origin, direction);
const intersects = raycaster.intersectObjects (objects, recursive);
Mouse Position Conversion const mouse = new THREE .Vector2 ();
function updateMouse (event ) {
mouse.x = (event.clientX / window .innerWidth ) * 2 - 1 ;
mouse.y = -(event.clientY / window .innerHeight ) * 2 + 1 ;
}
function updateMouseCanvas (event, canvas ) {
const rect = canvas.getBoundingClientRect ();
mouse.x = ((event.clientX - rect.left ) / rect.width ) * 2 - 1 ;
mouse.y = -((event.clientY - rect.top ) / rect.height ) * 2 + 1 ;
}
Touch Support function onTouchStart (event ) {
event.preventDefault ();
if (event.touches .length === 1 ) {
const touch = event.touches [0 ];
mouse.x = (touch.clientX / window .innerWidth ) * 2 - 1 ;
mouse.y = -(touch.clientY / window .innerHeight ) * 2 + 1 ;
raycaster.setFromCamera (mouse, camera);
const intersects = raycaster.intersectObjects (clickableObjects);
if (intersects.length > 0 ) {
handleSelection (intersects[0 ]);
}
}
}
renderer.domElement .addEventListener ("touchstart" , onTouchStart);
Raycaster Options const raycaster = new THREE .Raycaster ();
raycaster.near = 0 ;
raycaster.far = 100 ;
raycaster.params .Line .threshold = 0.1 ;
raycaster.params .Points .threshold = 0.1 ;
raycaster.layers .set (1 );
Efficient Raycasting
const clickables = [mesh1, mesh2, mesh3];
const intersects = raycaster.intersectObjects (clickables, false );
mesh1.layers .set (1 );
raycaster.layers .set (1 );
let lastRaycast = 0 ;
function onMouseMove (event ) {
const now = Date .now ();
if (now - lastRaycast < 50 ) return ;
lastRaycast = now;
}
Camera Controls
OrbitControls import { OrbitControls } from "three/addons/controls/OrbitControls.js" ;
const controls = new OrbitControls (camera, renderer.domElement );
controls.enableDamping = true ;
controls.dampingFactor = 0.05 ;
controls.minPolarAngle = 0 ;
controls.maxPolarAngle = Math .PI / 2 ;
controls.minAzimuthAngle = -Math .PI / 4 ;
controls.maxAzimuthAngle = Math .PI / 4 ;
controls.minDistance = 2 ;
controls.maxDistance = 50 ;
controls.enableRotate = true ;
controls.enableZoom = true ;
controls.enablePan = true ;
controls.autoRotate = true ;
controls.autoRotateSpeed = 2.0 ;
controls.target .set (0 , 1 , 0 );
function animate ( ) {
controls.update ();
renderer.render (scene, camera);
}
OrbitControls Programmatic Methods (r183)
controls.dolly (1.5 );
controls.pan (deltaX, deltaY);
controls.rotate (deltaAzimuth, deltaPolar);
controls.cursorStyle = { orbit : "grab" , pan : "move" , dolly : "zoom-in" };
FlyControls import { FlyControls } from "three/addons/controls/FlyControls.js" ;
const controls = new FlyControls (camera, renderer.domElement );
controls.movementSpeed = 10 ;
controls.rollSpeed = Math .PI / 24 ;
controls.dragToLook = true ;
function animate ( ) {
controls.update (clock.getDelta ());
renderer.render (scene, camera);
}
FirstPersonControls import { FirstPersonControls } from "three/addons/controls/FirstPersonControls.js" ;
const controls = new FirstPersonControls (camera, renderer.domElement );
controls.movementSpeed = 10 ;
controls.lookSpeed = 0.1 ;
controls.lookVertical = true ;
controls.constrainVertical = true ;
controls.verticalMin = Math .PI / 4 ;
controls.verticalMax = (Math .PI * 3 ) / 4 ;
function animate ( ) {
controls.update (clock.getDelta ());
}
PointerLockControls import { PointerLockControls } from "three/addons/controls/PointerLockControls.js" ;
const controls = new PointerLockControls (camera, document .body );
document .addEventListener ("click" , () => {
controls.lock ();
});
controls.addEventListener ("lock" , () => {
console .log ("Pointer locked" );
});
controls.addEventListener ("unlock" , () => {
console .log ("Pointer unlocked" );
});
const velocity = new THREE .Vector3 ();
const direction = new THREE .Vector3 ();
const moveForward = false ;
const moveBackward = false ;
document .addEventListener ("keydown" , (event ) => {
switch (event.code ) {
case "KeyW" :
moveForward = true ;
break ;
case "KeyS" :
moveBackward = true ;
break ;
}
});
function animate ( ) {
if (controls.isLocked ) {
direction.z = Number (moveForward) - Number (moveBackward);
direction.normalize ();
velocity.z -= direction.z * 0.1 ;
velocity.z *= 0.9 ;
controls.moveForward (-velocity.z );
}
}
TrackballControls import { TrackballControls } from "three/addons/controls/TrackballControls.js" ;
const controls = new TrackballControls (camera, renderer.domElement );
controls.rotateSpeed = 2.0 ;
controls.zoomSpeed = 1.2 ;
controls.panSpeed = 0.8 ;
controls.staticMoving = true ;
function animate ( ) {
controls.update ();
}
MapControls import { MapControls } from "three/addons/controls/MapControls.js" ;
const controls = new MapControls (camera, renderer.domElement );
controls.enableDamping = true ;
controls.dampingFactor = 0.05 ;
controls.screenSpacePanning = false ;
controls.maxPolarAngle = Math .PI / 2 ;
TransformControls Gizmo for moving/rotating/scaling objects.
import { TransformControls } from "three/addons/controls/TransformControls.js" ;
const transformControls = new TransformControls (camera, renderer.domElement );
scene.add (transformControls);
transformControls.attach (selectedMesh);
transformControls.setMode ("translate" );
transformControls.setSpace ("local" );
transformControls.setSize (1 );
transformControls.addEventListener ("dragging-changed" , (event ) => {
orbitControls.enabled = !event.value ;
});
transformControls.addEventListener ("change" , () => {
renderer.render (scene, camera);
});
window .addEventListener ("keydown" , (event ) => {
switch (event.key ) {
case "g" :
transformControls.setMode ("translate" );
break ;
case "r" :
transformControls.setMode ("rotate" );
break ;
case "s" :
transformControls.setMode ("scale" );
break ;
case "Escape" :
transformControls.detach ();
break ;
}
});
DragControls import { DragControls } from "three/addons/controls/DragControls.js" ;
const draggableObjects = [mesh1, mesh2, mesh3];
const dragControls = new DragControls (
draggableObjects,
camera,
renderer.domElement ,
);
dragControls.addEventListener ("dragstart" , (event ) => {
orbitControls.enabled = false ;
event.object .material .emissive .set (0xaaaaaa );
});
dragControls.addEventListener ("drag" , (event ) => {
event.object .position .y = 0 ;
});
dragControls.addEventListener ("dragend" , (event ) => {
orbitControls.enabled = true ;
event.object .material .emissive .set (0x000000 );
});
Selection System
Click to Select const raycaster = new THREE .Raycaster ();
const mouse = new THREE .Vector2 ();
let selectedObject = null ;
function onMouseDown (event ) {
mouse.x = (event.clientX / window .innerWidth ) * 2 - 1 ;
mouse.y = -(event.clientY / window .innerHeight ) * 2 + 1 ;
raycaster.setFromCamera (mouse, camera);
const intersects = raycaster.intersectObjects (selectableObjects);
if (selectedObject) {
selectedObject.material .emissive .set (0x000000 );
}
if (intersects.length > 0 ) {
selectedObject = intersects[0 ].object ;
selectedObject.material .emissive .set (0x444444 );
} else {
selectedObject = null ;
}
}
Box Selection import { SelectionBox } from "three/addons/interactive/SelectionBox.js" ;
import { SelectionHelper } from "three/addons/interactive/SelectionHelper.js" ;
const selectionBox = new SelectionBox (camera, scene);
const selectionHelper = new SelectionHelper (renderer, "selectBox" );
document .addEventListener ("pointerdown" , (event ) => {
selectionBox.startPoint .set (
(event.clientX / window .innerWidth ) * 2 - 1 ,
-(event.clientY / window .innerHeight ) * 2 + 1 ,
0.5 ,
);
});
document .addEventListener ("pointermove" , (event ) => {
if (selectionHelper.isDown ) {
selectionBox.endPoint .set (
(event.clientX / window .innerWidth ) * 2 - 1 ,
-(event.clientY / window .innerHeight ) * 2 + 1 ,
0.5 ,
);
}
});
document .addEventListener ("pointerup" , (event ) => {
selectionBox.endPoint .set (
(event.clientX / window .innerWidth ) * 2 - 1 ,
-(event.clientY / window .innerHeight ) * 2 + 1 ,
0.5 ,
);
const selected = selectionBox.select ();
console .log ("Selected objects:" , selected);
});
Hover Effects const raycaster = new THREE .Raycaster ();
const mouse = new THREE .Vector2 ();
let hoveredObject = null ;
function onMouseMove (event ) {
mouse.x = (event.clientX / window .innerWidth ) * 2 - 1 ;
mouse.y = -(event.clientY / window .innerHeight ) * 2 + 1 ;
raycaster.setFromCamera (mouse, camera);
const intersects = raycaster.intersectObjects (hoverableObjects);
if (hoveredObject) {
hoveredObject.material .color .set (hoveredObject.userData .originalColor );
document .body .style .cursor = "default" ;
}
if (intersects.length > 0 ) {
hoveredObject = intersects[0 ].object ;
if (!hoveredObject.userData .originalColor ) {
hoveredObject.userData .originalColor =
hoveredObject.material .color .getHex ();
}
hoveredObject.material .color .set (0xff6600 );
document .body .style .cursor = "pointer" ;
} else {
hoveredObject = null ;
}
}
window .addEventListener ("mousemove" , onMouseMove);
Keyboard Input const keys = {};
document .addEventListener ("keydown" , (event ) => {
keys[event.code ] = true ;
});
document .addEventListener ("keyup" , (event ) => {
keys[event.code ] = false ;
});
function update ( ) {
const speed = 0.1 ;
if (keys["KeyW" ]) player.position .z -= speed;
if (keys["KeyS" ]) player.position .z += speed;
if (keys["KeyA" ]) player.position .x -= speed;
if (keys["KeyD" ]) player.position .x += speed;
if (keys["Space" ]) player.position .y += speed;
if (keys["ShiftLeft" ]) player.position .y -= speed;
}
World-Screen Coordinate Conversion
World to Screen function worldToScreen (position, camera ) {
const vector = position.clone ();
vector.project (camera);
return {
x : ((vector.x + 1 ) / 2 ) * window .innerWidth ,
y : (-(vector.y - 1 ) / 2 ) * window .innerHeight ,
};
}
const screenPos = worldToScreen (mesh.position , camera);
element.style .left = screenPos.x + "px" ;
element.style .top = screenPos.y + "px" ;
Screen to World function screenToWorld (screenX, screenY, camera, targetZ = 0 ) {
const vector = new THREE .Vector3 (
(screenX / window .innerWidth ) * 2 - 1 ,
-(screenY / window .innerHeight ) * 2 + 1 ,
0.5 ,
);
vector.unproject (camera);
const dir = vector.sub (camera.position ).normalize ();
const distance = (targetZ - camera.position .z ) / dir.z ;
return camera.position .clone ().add (dir.multiplyScalar (distance));
}
Ray-Plane Intersection function getRayPlaneIntersection (mouse, camera, plane ) {
const raycaster = new THREE .Raycaster ();
raycaster.setFromCamera (mouse, camera);
const intersection = new THREE .Vector3 ();
raycaster.ray .intersectPlane (plane, intersection);
return intersection;
}
const groundPlane = new THREE .Plane (new THREE .Vector3 (0 , 1 , 0 ), 0 );
const worldPos = getRayPlaneIntersection (mouse, camera, groundPlane);
Event Handling Best Practices class InteractionManager {
constructor (camera, renderer, scene ) {
this .camera = camera;
this .renderer = renderer;
this .scene = scene;
this .raycaster = new THREE .Raycaster ();
this .mouse = new THREE .Vector2 ();
this .clickables = [];
this .bindEvents ();
}
bindEvents ( ) {
const canvas = this .renderer .domElement ;
canvas.addEventListener ("click" , (e ) => this .onClick (e));
canvas.addEventListener ("mousemove" , (e ) => this .onMouseMove (e));
canvas.addEventListener ("touchstart" , (e ) => this .onTouchStart (e));
}
updateMouse (event ) {
const rect = this .renderer .domElement .getBoundingClientRect ();
this .mouse .x = ((event.clientX - rect.left ) / rect.width ) * 2 - 1 ;
this .mouse .y = -((event.clientY - rect.top ) / rect.height ) * 2 + 1 ;
}
getIntersects ( ) {
this .raycaster .setFromCamera (this .mouse , this .camera );
return this .raycaster .intersectObjects (this .clickables , true );
}
onClick (event ) {
this .updateMouse (event);
const intersects = this .getIntersects ();
if (intersects.length > 0 ) {
const object = intersects[0 ].object ;
if (object.userData .onClick ) {
object.userData .onClick (intersects[0 ]);
}
}
}
addClickable (object, callback ) {
this .clickables .push (object);
object.userData .onClick = callback;
}
dispose ( ) {
}
}
const interaction = new InteractionManager (camera, renderer, scene);
interaction.addClickable (mesh, (intersect ) => {
console .log ("Clicked at:" , intersect.point );
});
Performance Tips
Limit raycasts : Throttle mousemove handlers
Use layers : Filter raycast targets
Simple collision meshes : Use invisible simpler geometry for raycasting
Disable controls when not needed : controls.enabled = false
Batch updates : Group interaction checks
const complexMesh = loadedModel;
const collisionMesh = new THREE .Mesh (
new THREE .BoxGeometry (1 , 1 , 1 ),
new THREE .MeshBasicMaterial ({ visible : false }),
);
collisionMesh.userData .target = complexMesh;
clickables.push (collisionMesh);
See Also
threejs-fundamentals - Camera and scene setup
threejs-animation - Animating interactions
threejs-shaders - Visual feedback effects
Connections
Domain: [[Design & Kreativitaet]]
Kategorie: [[3D & Animation]]
Navigation: [[Skills Uebersicht]], [[Home]]