super-hands

repository·master·Indexed 18 days ago

https://github.com/c-frame/aframe-super-hands-component

An all-in-one natural hand controller interaction library for A-Frame (v3.0.6). It enables gestures such as grabbing, stretching, and dragging using controllers, touch, or mouse input through a two-part architecture consisting of a core component for input interpretation and reaction components (hoverable, grabbable, stretchable, draggable, and droppable) for entity behavior.

Tokens
5K
Snippets
6
Records
19
Agent score
13%

What's inside super-hands

  1. How super-hands works: Core vs Reaction Components

    master

    The super-hands library uses a two-part architecture to enable natural interactions (gestures) in A-Frame:

    1. Core Component (super-hands): This component is placed on the user's input devices (tracked controllers, cursors, or raycasters). Its job is to gather raw input and collision data and interpret them into high-level gestures. It then communicates these gestures to targeted entities via custom events.

    2. Reaction Components: These are placed on the entities you want to interact with (e.g., a box or a sphere). They listen for the gesture events emitted by the Core component and execute the corresponding behavior (like moving, resizing, or changing color).

    Supported Gestures:

    • Hover: Holding a controller in an entity's collision space or pointing a cursor/laser at it.
    • Grab: Pressing a button while hovering an entity.
    • Stretch: Grabbing an entity with two hands and resizing it.
    • Drag-drop: Activating one entity and gesturing to another to interact with it.
    <!-- Core component on the controller -->
    <a-entity super-hands hand-controls="hand: left"></a-entity>
    
    <!-- Reaction component on the target object -->
    <a-box grabbable hoverable></a-box>
  2. The super-hands component

    master

    The super-hands component is the core of the library. It manages gesture events by communicating user input and entity collisions.

    Placement:

    • Attach super-hands to controller entities (or the camera for gaze interaction).
    • You must also include a collision detection component (e.g., raycaster, aframe-extras sphere-collider, or aframe-physics-extras physics-collider) on the same entity or a child entity of the super-hands entity.
  3. How gesture and response are separated

    master

    Super Hands uses a decoupled architecture where the super-hands component handles the gesture (detecting input) and the reaction components (like grabbable or stretchable) handle the response (how the entity actually behaves).

    This separation allows you to decide how different entities react to the same gesture. For example, a grab gesture might make one entity move with the hand, while another entity simply spawns a new object. You achieve this by attaching different reaction components to your entities.

  4. How to implement custom reaction components

    master

    You can create custom components to react to gestures in two ways:

    1. A-Frame style: Listen for the custom A-Frame events and states emitted by the reaction components (e.g., grabbed, clicked, dragover).
    2. HTML style: Use the Global Event Handlers Web API to handle standard mouse events (like onclick) which super-hands triggers to mimic VR interactions.

    Crucial Requirement: Gesture Acceptance When a custom component responds to a gesture, it must call .preventDefault() on the event. This signals to super-hands that the gesture has been accepted, preventing it from searching for other overlapping or nested entities that might also match the gesture.

  5. Install super-hands via Browser (CDN)

    master

    For direct browser usage, include the super-hands script in your <head>.

    For A-Frame 1.4.2 and below: Include aframe, aframe-extras, and super-hands.

    For A-Frame 1.5.0 and above: You must include a workaround to prevent conflicts with the built-in A-Frame grabbable component by deleting it from the AFRAME.components object before loading super-hands.

    <!-- A-Frame 1.5.0+ Setup Example -->
    <head>
      <script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
      <script>
        delete AFRAME.components["grabbable"];
      </script>
      <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-extras@7.5.x/dist/aframe-extras.min.js"></script>
      <script src="https://unpkg.com/super-hands@^3.0.6/dist/super-hands.min.js"></script>
    </head>
  6. Implement reaction components for super-hands

    master

    To make an entity respond to super-hands gestures, you must attach specific "reaction components" to it. The super-hands component manages the logic and dispatches events, while these components listen for those events to change the entity's state (e.g., making it grabbable or hoverable).

    Available reaction components include:

    • hoverable
    • grabbable
    • stretchable
    • draggable
    • droppable
    • drag-droppable
    • clickable
  7. Basic usage example for super-hands

    master

    This example demonstrates a minimal setup where two hands (left and right) use a sphere-collider to interact with a blue box that is hoverable, grabbable, stretchable, draggable, and droppable.

    <a-scene>
      <a-assets></a-assets>
      <a-entity>
        <a-camera></a-camera>
        <a-entity sphere-collider="objects: a-box" super-hands hand-controls="hand: left"></a-entity>
        <a-entity sphere-collider="objects: a-box" super-hands hand-controls="hand: right"></a-entity>
      </a-entity>
      
      <a-box 
        hoverable 
        grabbable 
        stretchable 
        draggable 
        droppable 
        color="blue" 
        position="0 0 -1">
      </a-box>
    </a-scene>
  8. Handle super-hands gesture events

    master

    When an interaction occurs, super-hands emits gesture events from the target entity (the entity being interacted with). The entity that super-hands is attached to is provided in the event detail as the hand property.

    Available Gesture Events:

    TypeDescriptionTargetdetail object
    hover-startCollided with entitycollided entityhand: super-hands entity
    hover-endNo longer collided with entitycollided entityhand: super-hands entity
    grab-startButton pressed while collided with entity and hand is emptycollided entityhand: super-hands entity
    grab-endButton released after grab-startcollided entityhand: super-hands entity
    stretch-startBoth controllers have button pressed while collided with entitycollided entityhand: super-hands entity, secondHand: second controller entity
    stretch-endRelease of button after stretch-startcollided entityhand: super-hands entity
    drag-startDrag-drop button pressed while collided with entity and hand is emptycollided entityhand: super-hands entity
    drag-endDrag-drop button released while dragging an entitydragged entityhand: super-hands entity
    dragover-startCollision with entity while dragging another entitycollided entity & held entityhand: super-hands entity, hovered: collided entity, carried: held entity
    dragover-endNo longer collided with entity from dragover-startcollided entity & held entityhand: super-hands entity, hovered: collided entity, carried: held entity
    drag-dropButton released while holding an entity and collided with anothercollided entity & held entityhand: super-hands entity, dropped: carried entity, on (carried entity only): receiving entity

    Important Notes:

    • Event Bubbling: Gesture events bubble to the closest parent with a related reaction component. This allows you to make a child (like a door handle) collidable while the parent (the door) handles the reaction.
    • LIFO/Nearest-First: If multiple collision zones overlap, super-hands uses a LIFO stack of collided entities and a nearest-first queue of raycasted entities to determine the target.
    • Drag-Drop on property: For the receiving entity in a drag-drop event, the on property in the detail is null. Use event.target instead.
  9. Use HTML Global Event Handlers for super-hands

    master

    You can use standard HTML event attributes on entities to react to super-hands interactions. These handlers receive a MouseEvent where the relatedTarget property is used to identify the interacting entity.

    entity HTML attributeconditionsevent.relatedTarget
    onmouseoverhovering in an entity's collision zonesuper-hands entity
    onmouseoutleaving an entity's collision zonesuper-hands entity
    onmousedowngrab started while collided with entitysuper-hands entity
    onmouseupgrab ended while collided with entitycontroller entity
    onclickgrab started and then ended while collided with entitycontroller entity
    ondragstartdrag-drop started while collided with entitycontroller entity
    ondragenddrag-drop started while collided with entitycontroller entity
    ondragenterhovering in an entity's collision zone while drag-dropping another entitythe other entity*
    ondragleaveleaving an entity's collision zone while drag-dropping another entitythe other entity*
    ondropdrag-drop ended while holding an entity over a targetthe other entity*

    *Note: For drag-dropping events, the relatedTarget points to the other entity involved in the interaction (the one being dragged or the target being dropped upon).

  10. Use the stretchable component

    master

    The stretchable component allows an entity to rescale when grabbed by two controllers simultaneously as they move closer or further apart.

    States:

    • stretched: Added to the entity while it is grabbed with two hands.

    Schema:

    PropertyDescriptionDefault Value
    startButtonsWhich button events to accept to start stretch[]
    endButtonsWhich button events to accept to end stretch[]
    usePhysicsWhether to update physics body shapes with scale changes ('ifavailable' or 'never')'ifavailable'
    invertReverse the direction of scaling in relation to controller movementfalse
    physicsUpdateRateMilliseconds between each update to the physics bodies100

    Physics Note: Rescaling physics shapes (box and sphere) is currently only possible when using the 'local' physics driver. If using other drivers, set usePhysics: never to avoid errors, though this will cause a sync loss between appearance and behavior.