StringImpulse Module

Design immersive hover responses with cursor-driven micro-interactions. StringImpulse converts pointer velocity into controlled translation and rotation, letting elements lean, lift, or react with tactile realism.

Activation primer: Add string="impulse" to every element you want StringImpulse to energise. Supply string-id="your-id" when you need a stable handle for events, mirrors, or string-copy-from; otherwise StringTune generates one automatically.

HTML Attributes

AttributeTypeDefaultControlsPractical notes
string-position-strengthnumber3Scale of cursor velocity converted to positional forceRaise for snappier lifts; negative values invert direction
string-position-tensionnumber0.05Spring pull-back toward originIncrease to reduce drift; typical range 0.040.12
string-position-frictionnumber0.15Per-frame damping of velocityHigher values calm jitter; keep between 0.10.3
string-position-max-velocitynumber10Clamp for positional speed (px/frame)Lift for high-energy gestures; lower for subtle motion
string-position-update-thresholdnumber0.1Minimal delta before writing --push-x/--push-yRaise to reduce CSS churn; drop for micro precision
string-max-offsetnumber220Hard clamp for displacement (px)Acts as safety net; match component scale
string-continuous-pushbooleantrueApply impulses on every move (true) or once per hover (false)Set to false for single “kick” interactions
string-rotation-strengthnumber0.75Torque multiplier for angular impulseNegative values invert tilt direction
string-rotation-tensionnumber0.06Restoring torque toward 0degAlign with position tension for balanced feel
string-rotation-frictionnumber0.18Angular damping per frameIncrease to calm wobble; start 0.150.35
string-rotation-max-angular-velocitynumber6Clamp for angular speed (deg/frame)Prevents violent spins; raise carefully
string-rotation-max-anglenumber18Absolute rotation clamp (deg)Lower for UI controls, higher for hero visuals
string-rotation-update-thresholdnumber0.15Minimal delta before writing --push-rotationLift if transforms flicker on high-refresh panels
string-sleep-epsilonnumber0.01Threshold to snap back to zero when nearly stillRaise slightly if motion never settles

Defaults hydrate from StringTune.setupSettings(). Override globally via stringTune.use(StringImpulse, { ... }) or per element with attributes.

Module Snapshot

  • Activation attribute: string="impulse"
  • CSS variables populated: --push-x, --push-y, --push-rotation (raw numbers; add units in CSS)
  • Event hooks: object:impulse:<id>:move, object:impulse:<id>:rotate, object:impulse:<id>:side
  • Best suited for: cards, buttons, hero visuals, cursor-followed accents
  • Plays well with: StringCursor, mirror objects (string-copy-from), smooth scroll modes

Basic Usage

  • Ensure the engine is already bootstrapped elsewhere in the project. When you are wiring the module in isolation:
import StringTune, { StringImpulse } from '@fiddle-digital/string-tune';

const stringTune = StringTune.getInstance();
stringTune.use(StringImpulse);
stringTune.start(60);
  • Annotate responsive elements with string="impulse" (or data-string="impulse").
  • Consume the variables in CSS—StringImpulse never mutates transforms automatically.
<button string="impulse" string-position-strength="2.2" class="cta">Explore</button>
.cta {
  transform: translate(calc(var(--push-x, 0) * 1px), calc(var(--push-y, 0) * 1px)) rotate(calc(var(--push-rotation, 0) * 1deg));
  transform-origin: 50% 50%;
  transition: transform 120ms ease-out;
  will-change: transform;
}

How the Module Behaves

  • Impulse capture: on each mouse move, cursor velocity plus relative position to the element centre determine fresh impulses. Only elements beneath the pointer receive updates.
  • Spring simulation: offsets follow a spring–damper loop, clamped by position-max-velocity and max-offset. Rotation mirrors this logic in degrees.
  • Sleep mode: once displacement and velocity fall below sleep-epsilon, values snap to zero and CSS writes pause.
  • Threshold gating: CSS variables update only when deltas exceed the configured thresholds, keeping layout thrash low.
  • Latch logic: continuous-push=false enables one-shot impulses; the latch resets when the cursor leaves the element.

Event Signals

Channel patternPayloadFired whenIdeal for
object:impulse:<id>:move{ x: number; y: number; }Rounded --push-x/--push-y values change beyond position-update-thresholdDrive transform stacks, parallax overlays, particle emitters
object:impulse:<id>:rotate{ rotation: number; }Smoothed rotation exceeds rotation-update-thresholdSync shadows, lighting gradients, tilt-driven shaders
object:impulse:<id>:side{ value: number; } (0=left, 1=right)Pointer crosses the element while impulse is activeCrossfade hotspots, audio panning, directional cues

All events share the DOM object's string-id (or generated ID) as <id>. Subscribe via the global event bus you receive from the StringTune instance:

const bus = stringTune; // getInstance already called elsewhere

bus.on('object:impulse:hero-card:move', ({ x, y }) => {
  // translate linked WebGL plane, apply easing if needed
});

Tip: when mirroring elements with string-copy-from, the originating object emits the events; mirrors simply inherit the CSS variables. Use the same <id> to stitch custom logic across layers.


StringImpulse rewards deliberate tuning—lean on the configuration matrix, iterate with the recipes, and lock in values once the interaction supports the product narrative.