Skip to content

siverson914/slarrow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🐍 Slarrow

An overlay arrow that slithers across the page like a snake — morphing smoothly from one bezier shape to another, taking as many crazy detours as you like, and steering like a car (it can't turn tighter than a minimum radius, so it always arrives pointing the right way).

Zero dependencies. One small ES module. Drop it on any page and point at things.

Slarrow demo

▶ Live demo — click anywhere to send the arrow there; tweak everything with the sliders.


Why

Tooltips and onboarding hints usually just appear. Slarrow gives you an arrow with personality: it crawls across the screen from wherever it is to wherever you point it, lengthening and shrinking as it goes, optionally wandering through a few random spots first like it's a little lost — then nails the landing, head pointed exactly where you asked.

It's named for slither + arrow (and it started life as the Streamload arrow).

Features

  • Snake-like crawl — the body follows the head along a continuous path; it morphs from a start shape into an end shape.
  • Car/truck/train steering — a configurable minimum turn radius (built on Dubins paths). It physically can't corner tighter than that, so it carves natural sweeping arcs and arrives head-on, never side-swiping the target.
  • Detours — send it through N random spots first (looks "lost"), or pass explicit waypoints with per-point headings.
  • Grow & shrink — independent start / mid / end body lengths, so it can swell long in the middle of a trip and shrink back at the end.
  • Fully shapeable — thickness, tail shape (round → needle), arrowhead size (length & width in px), and an open chevron head (two lines) or a solid filled triangle.
  • Drop-in overlay — renders into a fixed, pointer-events: none SVG layer, so it floats over your UI without intercepting clicks.
  • No dependencies, ~600 lines, MIT.

Install

It's a single ES module with zero dependencies. Copy src/js/slarrow.js into your project:

<script type="module">
  import { Slarrow } from './slarrow.js';
  // ...
</script>

Or pull it straight from a CDN (no build step):

import { Slarrow } from 'https://cdn.jsdelivr.net/gh/siverson914/slarrow/src/js/slarrow.js';

Quick start

import { Slarrow } from './slarrow.js';

const arrow = new Slarrow({ color: '#e1251b', width: 16, shadow: true });

// A "shape" is a cubic bezier: [tail, ctrl1, ctrl2, head].
// arrowAt() builds one whose head sits at {x,y} pointing EXACTLY at `angle`.
arrow.set(Slarrow.arrowAt({ x: 120, y: 120, angle: 0 }));

// Fly to a new shape, taking 3 random detours, steering like a car.
await arrow.flyTo(
  Slarrow.arrowAt({ x: 700, y: 400, angle: Math.PI }),
  {
    detours: 3,        // visit 3 random spots first
    duration: 2600,    // ms
    turnRadius: 120,   // px — it can't turn tighter than this
    midLength: 480,    // grow long mid-flight, then settle back
  }
);

Or send the head to a point and let it derive the end shape:

arrow.flyToPoint(event.clientX, event.clientY, { detours: 2, turnRadius: 90 });

API

new Slarrow(options)

option default meaning
color '#e1251b' fill / stroke color
width 16 body thickness (px)
shadow true soft drop shadow; or {dx,dy,blur,color,opacity}
tail 0.5 tail shape: 0 round/blunt → 1 sharp needle
headLength 28 arrowhead length (px)
headWidth 30 arrowhead width across (px)
openHead false true = open chevron (two lines); false = filled triangle
smoothness 0.5 0..1 fallback turn-radius laziness when turnRadius isn't given
samples 90 body smoothness (points)
container document.body element the overlay mounts into
zIndex 9999 overlay stacking

All of these are also live properties (arrow.openHead = true, etc.); call set/flyTo to re-render.

Methods

  • arrow.set(shape) — snap to a shape instantly (no animation).
  • arrow.flyTo(targetShape, opts)Promise — animate to a shape. Opts: detours, waypoints, duration, turnRadius, midLength, smoothness, easing, seed.
  • arrow.flyToPoint(x, y, opts)Promise — fly the head to a point, auto-deriving the end shape.
  • arrow.destroy() — remove the overlay.

Statics

  • Slarrow.arrowAt({ x, y, angle, length, curve }) → shape — a curved arrow whose head is at {x,y} pointing exactly at angle (radians, 0 = →).
  • Slarrow.randomWaypoints(n, { width, height, padding, seed })[[x,y,angle], …] — N random spots (pass seed for reproducibility).
  • Slarrow.shapeLength(shape) → px — arc length of a shape (handy for matching midLength units).

Shapes & waypoints

A shape is a cubic bezier as four [x, y] points: [tail, ctrl1, ctrl2, head]. The last point is the tip; the arrowhead points along the curve's tangent there.

A waypoint is [x, y] or [x, y, angle] — the optional angle pins the heading the snake must be travelling as it crosses that point.

How the steering works

The path between each pose (position + heading) is the shortest Dubins path: circular arcs of exactly the turn radius joined by straight runs. Because curvature never exceeds 1 / turnRadius, the arrow can't pivot in place — to reach a target behind it, it swings out in a wide arc (or a full loop) and comes back aligned. Crank turnRadius up and it behaves like a train needing a huge yard to turn around.

License

MIT — see LICENSE.

About

An overlay arrow that slithers across the page like a snake — morphing bezier shapes with car-like (Dubins) steering. Zero deps.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors