npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

curved-arrows

v0.3.0

Published

Draw S-curved arrows between points or shapes

Downloads

3,865

Readme

Curved Arrows

version license

A set of functions for drawing S-curved arrows between points and shapes.

  • getArrow - For point-to-point arrows (has glitches, not ready yet).
  • getBoxToBoxArrow - For rectangle-to-rectangle arrows.

demo animation

👉 Demo | How it works

You may also want to see steveruizok's perfect-arrows, it's smarter but the start point and the end point are less predictable.

Installation

npm i curved-arrows

or

yarn add curved-arrows

Usage

The functions in this library has similar arguments and return values to steveruizok's perfect-arrows. Notable differences are options and the return values containing two control points, one for start point and one end point, instead of one, to represent an S-curve.

The return values provide only the information needed to draw an arrow. You'll need to draw the arrow yourself using your technology of choice. See below for an example using React and SVG.

getArrow(x0, y0, x1, y1, options)

The getArrow function accepts the position of two points and returns an array containing this information:

  • four points: start, end, and two control points (one for start, one for end)
  • two angles: end and start

You can use this information to draw an S-curve and arrow heads. You can use the options object to tweak the return values.

const arrowHeadSize = 9
const arrow = getArrow(0, 0, 100, 200, {
  padStart: 0,
  padEnd: arrowHeadSize,
})
const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae, as] = arrow

Arguments

| Argument | Type | Description | | -------- | ------ | --------------------------------------------------------------------------- | | x0 | number | The x position of the starting point. | | y0 | number | The y position of the starting point. | | x1 | number | The x position of the ending point. | | y1 | number | The y position of the ending point. | | options| object | An (optional) object containing one or more of the options described below. |

Options

| Option | Type | Default | Description | | --------------------- | ------ | :-----: | ------------------------------------------------------------ | | padStart | number | 0 | How far the arrow's starting point should be from the provided starting point. | | padEnd | number | 0 | How far the arrow's ending point should be from the provided ending point. | | controlPointStretch | number | 50 | Enforce a minimal distance from the arrow's starting/ending point to the control points making the curve. (demo, more explanation, code) |

Returns

| Argument | Type | Description | | -------- | ------ | ------------------------------------------------ | | sx | number | The x position of the (padded) starting point. | | sy | number | The y position of the (padded) starting point. | | c1x | number | The x position of the control point of the starting point. | | c1y | number | The y position of the control point of the starting point. | | c2x | number | The x position of the control point of the ending point. | | c2y | number | The y position of the control point of the ending point. | | ex | number | The x position of the (padded) ending point. | | ey | number | The y position of the (padded) ending point. | | ae | number | The angle (in degree) for an ending arrowhead. | | as | number | The angle (in degree) for a starting arrowhead. |


getBoxToBoxArrow(x0, y0, w0, h0, x1, y1, w1, h1, options)

The getBoxToBoxArrow function accepts the position and dimensions of two boxes (or rectangles) and returns an array containing this information:

  • four points: start, end, and two control points (one for start, one for end)
  • two angles: end and start

You can use this information to draw an S-curve and arrow heads. You can use the options object to tweak the return values.

Note: The options and values returned by getBoxToBoxArrow are in the same format as the options and values for getArrow.

const arrowHeadSize = 9
const arrow = getArrow(0, 0, 200, 100, 300, 50, 200, 100, {
  padStart: 0,
  padEnd: arrowHeadSize,
})
const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae, as] = arrow

Arguments

| Argument | Type | Description | | -------- | ------ | --------------------------------------------------------------------------- | | x0 | number | The x position of the first rectangle. | | y0 | number | The y position of the first rectangle. | | w0 | number | The width of the first rectangle. | | h0 | number | The height of the first rectangle. | | x1 | number | The x position of the second rectangle. | | y1 | number | The y position of the second rectangle. | | w1 | number | The width of the second rectangle. | | h1 | number | The height of the second rectangle. | | options| object | An (optional) object containing one or more of the options described below. |

Options

See options in getArrow above. (Both functions use the same options object.)

Returns

See returns in getArrow above. (Both functions return the same set of values.)

Example: A React Arrow Component

import * as React from 'react'
import { getArrow } from 'curved-arrows'

export function Arrow() {
  const p1 = { x: 100, y: 100 }
  const p2 = { x: 300, y: 200 }
  const arrowHeadSize = 9
  const color = 'black'
  const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae] = getArrow(p1.x, p1.y, p2.x, p2.y, {
    padEnd: arrowHeadSize,
  })

  return (
    <svg
      width="100%"
      height="100%"
      xmlns="http://www.w3.org/2000/svg">
      <path
        d={`M ${sx} ${sy} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${ex} ${ey}`}
        stroke={color}
        strokeWidth={arrowHeadSize / 2}
        fill="none"
      />
      <polygon
        points={`0,${-arrowHeadSize} ${arrowHeadSize *
          2},0, 0,${arrowHeadSize}`}
        transform={`translate(${ex}, ${ey}) rotate(${ae})`}
        fill={color}
      />
    </svg>
  )
}

Author

@hialexwang