Rope Physics
A 25-segment Verlet rope with both ends anchored responds to mouse dragging in real time: the length constraint is resolved in 10 iterations per frame, gravity pulls nodes downward. Sharp on Retina, loop paused off-screen, static rope under reduced motion.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →
3 usage examples



How it works
The .fx-0390-root wrapper contains a .fx-0390-canvas that is 100 % wide by 300 px tall. At init, the script measures the width, applies devicePixelRatio and builds 26 nodes spaced 12 px apart. Nodes 0 and 25 are pinned at 20 % and 80 % of the width; the 24 others are free.
The loop uses Verlet integration: each frame, each free node computes its implicit velocity from its previous position (vx = (x − oldX) × 0.99), adds gravity (0.5 px/frame), then resolves the segment length constraint in 10 iterations. Scaling by dt / 16.67 (capped at 50 ms) ensures the simulation does not diverge after a background tab.
A mousedown (or touchstart) finds the nearest node within 15 px and attaches it to the pointer; mousemove (or touchmove) moves that node. An IntersectionObserver watches the root to pause the loop off-screen. Under reduced motion, the rope is drawn in its rest position with no loop.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the loop does not start and the rope is drawn at its rest position. The effect is visible and readable. - Keyboard: the interaction requires a mouse or finger (dragging a rope node). There is no natural keyboard equivalent for a canvas drag. Keyboard users cannot deform the rope.
- Touch:
touch-action: noneon the canvas prevents page scrolling when a finger slides over it. The effect responds to touch on mobile. - Decorative role: the canvas carries no text content. If the rope represents a named cable or path, expose that information as text nearby.
Browser compatibility
Canvas 2D (devicePixelRatio, IntersectionObserver, matchMedia), no dependency. IntersectionObserver available since Chrome 51, Firefox 55 and Safari 12.1. Not measured in Firefox and WebKit.
Without JavaScript, the canvas stays empty. Without IntersectionObserver, the simulation runs off-screen too. Without matchMedia, the rope animates even under reduced motion.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0390-root"><div class="physics-container"><canvas class="fx-0390-canvas"></canvas><span class="info-label">Help text</span></div></div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Number of segments (JS — SEGS = 25) |
25 segments | 10 segments give a coarse but very fast rope; 50 give a finer, more supple rope (more computation). |
Segment length (JS — SEGLEN = 12) |
12 px | 8 px for a shorter, tighter rope; 18 px for a looser, more drooping rope. |
Gravity (JS — n.y += vy * scale + 0.5 * scale) |
0.5 px/frame | 0.2 for an almost horizontal rope; 1 for a very heavy rope that falls fast. |
Rope colour (JS — ctx.strokeStyle = '#d946ef') |
#d946ef (fuchsia) |
Replace with your brand colour. Thickness is controlled via ctx.lineWidth = 6. |
Anchor positions (JS — x0 = 0.2 * W, x1 = 0.8 * W) |
20 % and 80 % of the width | 0 * W and 1 * W to anchor the rope at the extreme edges of the canvas. |
FAQ
SEGS are pinned. Their positions come from x0 and x1 at init. For movable anchors, remove pinned: true on those nodes and update them in the loop.