swoopyarrows makes swoopy arrows between things
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



Out of the crooked timber of JavaScript, no straight arrow was ever made.
— Immanuel Kant

Finally an open source project to match the scope of our ambition! A family of three path generators for making nice fun arrows. Use it more or less like d3.svg.line; the easiest thing is to just pass an array of two points, like [[0,0],[10,30]]. Each has x and y accessors and a couple other options.

Download, demo, demo source.

The only dependency is d3 v3. But it goes great with d3-jetpack! If you’re trying to annotate a bunch of things, you may also have more luck with Adam Pearce’s swoopyDrag.

Bring your own SVG markers. We typically use this simple arrowhead:

<marker id="arrowhead" viewBox="-10 -10 20 20" refX="0" refY="0" markerWidth="20" markerHeight="20" stroke-width="1" orient="auto"><polyline stroke-linejoin="bevel" points="-6.75,-6.75 0,0 -6.75,6.75"></polyline></marker>


Download. Connect points with circular arcs. The classic. Set angle to the angle the arrow should subtend, in radians, between 0 (basically straight) and Math.PI (a semicircle, 180º). It's not currently possible to subtend more than that.

var swoopy = swoopyArrow()
  .x(function(d) { return d[0]; })
  .y(function(d) { return d[1]; });

  .attr('marker-end', 'url(#arrowhead)')
  .attr("d", swoopy);


Download. Like a coiled telephone cord. Set the radius of the loop with radius; increase steps to add more coils — although it's only proportionate to the number of loops, not equal to, because I am bad at math and lazy.

var loopy = loopyArrow()
  .x(function(d) { return d[0]; })
  .y(function(d) { return d[1]; });

  .attr('marker-end', 'url(#arrowhead)')
  .attr("d", loopy);


Download. Follows a random path between two points. Increase steps to add more kinks; increase deviation to make the kinks deviate more from the path.

var kooky = kookyArrow()
  .x(function(d) { return d[0]; })
  .y(function(d) { return d[1]; });

  .attr('marker-end', 'url(#arrowhead)')
  .attr("d", kooky);

For an idea of how you might use the x and y accessors — you could set them to get the offsetLeft and offsetTop of DOM elements, so you can just pass an array of two DOM elements and generate an arrow between them:

var swoopBetweenElements = swoopyArrow()
  .x(function(d) { return d.offsetLeft; })
  .y(function(d) { return d.offsetTop; });

  .attr('marker-end', 'url(#arrowhead)')
  .datum([document.querySelector('h1'), document.querySelector('h2')])
  .attr("d", swoopBetweenElements);


  • Handle passing in more than two points (go through all three? choose the closest two?)
  • Put together a bunch of Adobe Illustrator-style SVG markers
  • The whole thing should just be a d3-shape custom curve module
  • Add droopy catenaries

Swoopy arrows have been in use since Egyptian hieroglyphics. They belong to no one ↪↺↷⟲⤣⤥⤴⤵⤶⤷⤹⤳⤻⤿⤺
Jennifer Daniel, patron saint

Prior art