Skip to main content الرئيسية المنشئون beko2210 firstbrain threejs-interaction
threejs-interaction 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.
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/BEKO2210/Firstbrain --skill threejs-interactionيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
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]]