• Stars
    star
    2,515
  • Rank 17,593 (Top 0.4 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Draw perfect arrows between points and shapes.

Perfect Arrows

A set of functions for drawing perfect arrows between points and shapes.

Example

πŸ‘‰ Demo

Edit example

Other languages

PortuguΓͺs (pt-BR)

Installation

npm i perfect-arrows

or

yarn add perfect-arrows

Usage

The functions in this library 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 React component with SVG.

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

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

  • three points: a start, end, and control point
  • three angles: an end, start, and center

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

const arrow = getArrow(0, 0, 100, 200, {
  bow: 0,
  stretch: 0.5,
  stretchMin: 0,
  stretchMax: 420,
  padStart: 0,
  padEnd: 0,
  flip: false,
  straights: true,
})

const [sx, sy, cx, cy, ex, ey, ae, as, sc] = 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
bow number 0 A value representing the natural bow of the arrow. At 0, all lines will be straight.
stretch number .5 The effect that the arrow's length will have, relative to its minStretch and maxStretch, on the bow of the arrow. At 0, the stretch will have no effect.
minStretch number 0 The length of the arrow where the line should be most stretched. Shorter distances than this will have no additional effect on the bow of the arrow.
maxStretch number 420 The length of the arrow at which the stretch should have no effect.
padStart number 0 How far the arrow's starting point should be from the provided start point.
padEnd number 0 How far the arrow's ending point should be from the provided end point.
flip boolean false Whether to reflect the arrow's bow angle.
straights boolean true Whether to use straight lines at 45 degree angles.

Returns

Argument Type Description
x0 number The x position of the (padded) starting point.
y0 number The y position of the (padded) starting point.
x1 number The x position of the (padded) ending point.
y1 number The y position of the (padded) ending point.
ae number The angle (in radians) for an ending arrowhead.
as number The angle (in radians) for a starting arrowhead.
ac number The angle (in radians) for a center arrowhead.

Example: A React Arrow Component

import * as React from "react"
import { getArrow } from "perfect-arrows"

export function PerfectArrow() {
  const p1 = { x: 64, y: 64 }
  const p2 = { x: 128, y: 96 }

  const arrow = getArrow(p1.x, p1.y, p2.x, p2.y, {
    padEnd: 20,
  })

  const [sx, sy, cx, cy, ex, ey, ae, as, ec] = arrow

  const endAngleAsDegrees = ae * (180 / Math.PI)

  return (
    <svg
      viewBox="0 0 720 480"
      style={{ width: 720, height: 480 }}
      stroke="#000"
      fill="#000"
      strokeWidth={3}
    >
      <circle cx={sx} cy={sy} r={4} />
      <path d={`M${sx},${sy} Q${cx},${cy} ${ex},${ey}`} fill="none" />
      <polygon
        points="0,-6 12,0, 0,6"
        transform={`translate(${ex},${ey}) rotate(${endAngleAsDegrees})`}
      />
    </svg>
  )
}

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 information for:

  • three points: a start, end, and control point
  • three angles: an end, start, and center

You can use this information to draw an arc 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 arrow = getBoxToBoxArrow(0, 0, 96, 128, 400, 200, 128, 96, {
  bow: 0,
  stretch: 0.5,
  stretchMin: 0,
  stretchMax: 420,
  padStart: 0,
  padEnd: 0,
  flip: false,
  straights: true,
})

const [sx, sy, cx, cy, ex, ey, ae, as, sc] = 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 Box-to-box Arrow Component

import * as React from "react"
import { getBoxToBoxArrow } from "perfect-arrows"

export function PerfectArrow() {
  const p1 = { x: 64, y: 64, w: 64, h: 64 }
  const p2 = { x: 128, y: 96, w: 64, h: 64 }

  const arrow = getBoxToBoxArrow(
    p1.x,
    p1.y,
    p1.w,
    p1.h,
    p2.x,
    p2.y,
    p2.w,
    p2.h,
    {
      bow: 0.2,
      stretch: 0.5,
      stretchMin: 40,
      stretchMax: 420,
      padStart: 0,
      padEnd: 20,
      flip: false,
      straights: true,
    }
  )

  const [sx, sy, cx, cy, ex, ey, ae, as, ec] = arrow

  const endAngleAsDegrees = ae * (180 / Math.PI)

  return (
    <svg
      viewBox="0 0 1280 720"
      style={{ width: 1280, height: 720 }}
      stroke="#000"
      fill="#000"
      strokeWidth={3}
    >
      <circle cx={sx} cy={sy} r={4} />
      <path d={`M${sx},${sy} Q${cx},${cy} ${ex},${ey}`} fill="none" />
      <polygon
        points="0,-6 12,0, 0,6"
        transform={`translate(${ex},${ey}) rotate(${endAngleAsDegrees})`}
      />
    </svg>
  )
}

Author

@steveruizok

More Repositories

1

perfect-freehand

Draw perfect pressure-sensitive freehand lines.
HTML
3,435
star
2

state-designer

State management with statecharts.
HTML
619
star
3

perfect-cursors

Perfect interpolation for multiplayer cursors.
TypeScript
494
star
4

telestrator

A disappearing drawing tool for your screen.
TypeScript
351
star
5

perfect-freehand-dart

Draw perfect freehand linesβ€”in Flutter.
Dart
233
star
6

globs

A globs-based vector editor.
TypeScript
233
star
7

rko

A state manager with undo, redo and persistence.
TypeScript
211
star
8

gotcha

Turn your Framer prototype into its own live developer spec.
CoffeeScript
114
star
9

liquorstore

A reactive store.
TypeScript
107
star
10

kdtype

A typing game for kids.
TypeScript
71
star
11

trashly

A reactive store.
TypeScript
53
star
12

polyclip-js

A JavaScript implementation of the Greiner-Hormann clipping algorithm.
TypeScript
47
star
13

arrows-playground

A canvas-based arrows playground.
TypeScript
37
star
14

state-designer-ide

A design environment for State Designer.
TypeScript
34
star
15

framer-moreutils

Expand Utils with some handy helper functions.
JavaScript
31
star
16

framework

A general-purpose component kit for Framer.
JavaScript
30
star
17

fontloader

Painlessly, reliably load local and web fonts into Framer prototypes.
CoffeeScript
30
star
18

arena-2022

An isometric game.
TypeScript
25
star
19

finder-toolbar-shortcuts

Easy shortcuts for Finder's toolbar.
Rich Text Format
25
star
20

react-motion-asteroids

An astroids-like game in React using Framer Motion.
TypeScript
24
star
21

personal-blog

A personal blog.
TypeScript
24
star
22

figma-plugin-perfect-freehand

A Figma plugin for drawing perfect freehand strokes.
TypeScript
24
star
23

replisketch

A collaborative drawing app built with Replicache.
TypeScript
19
star
24

framer-tools

Do good stuff fast in Framer X from the command line.
JavaScript
18
star
25

framer-controller

Control a Framer X component through overrides.
TypeScript
18
star
26

framer-button

A customizable button class for Framer prototypes.
CoffeeScript
15
star
27

tetris-react-state-designer

A Tetris implementation using React and State Designer.
TypeScript
14
star
28

framer-sublime-text

A Framer UI / Color Scheme / Syntax for Sublime Text
14
star
29

brush-engine

A brush engine for the browser.
TypeScript
13
star
30

together

A multiplayer experience.
TypeScript
13
star
31

inventory-react-state-designer

An inventory system in React and State Designer.
TypeScript
12
star
32

framer-md

A Material Design UI kit for Framer.
JavaScript
12
star
33

short-story

Small, self-contained interactive component demos.
JavaScript
12
star
34

framer-icon

Create SVG icons using this very simple module.
CoffeeScript
10
star
35

react-turtle

Turtle Graphics for React.
JavaScript
10
star
36

olc_rust_sketches

Learning rust with the olc Pixel Game Engine.
Rust
10
star
37

gnrng

A minimal seeded random number generator.
TypeScript
10
star
38

ActionLayer

An ActionLayer extends Layer, adding properties and functions designed to simplify managing events in Framer.
CoffeeScript
9
star
39

react-decal

A miniature canvas game engine in React.
TypeScript
9
star
40

quick-docs

Docs, quick.
JavaScript
8
star
41

framer-layout

Layout with grids in Framer.
CoffeeScript
8
star
42

arena-game

A tactical combat game in React.
TypeScript
6
star
43

react-use-maho

A state management tool based on statecharts.
TypeScript
6
star
44

snowcraft

Snowcraft brood war by Steve Ruiz.
TypeScript
6
star
45

FocusComponent

Control events among a group of layers.
CoffeeScript
5
star
46

state-designer-examples

Created with CodeSandbox
TypeScript
5
star
47

flow-docs

Docs for the flow component
JavaScript
4
star
48

MonokaiFade

Example of the monokai.nl-style fade effect.
TypeScript
3
star
49

perfect-freehand-signature

A pressure-based vector signature component.
3
star
50

learn-docs

Docs for the Learn Design System
JavaScript
3
star
51

bendy-arrows-playground

Created with CodeSandbox
TypeScript
3
star
52

short-story-sjs

Beautiful component previews for design, docs and demos.
TypeScript
2
star
53

unstyled-challenge

Design the web with strict limits on style.
JavaScript
2
star
54

steveruizok.github.io

UI/UX Portfolio
CSS
2
star
55

brushy-brushy

TypeScript
2
star
56

react-iso-engine

Isometric world engine written in React.
TypeScript
2
star
57

docs-mdx-cms

JavaScript
2
star
58

nextjs-content-starter

A Next.js static site with MDX.
TypeScript
2
star
59

stencil-refuge

App running on Refuge Restrooms API, built in Stencil.
JavaScript
1
star
60

emoji-picker-site

A tiny site for emoji picking.
CSS
1
star
61

st-lookbook

Webcomponents for previewing other components.
TypeScript
1
star
62

stencil-router-redux-demo

An example stencil project with stencil-router and stencil-redux working together.
HTML
1
star
63

framer-atomic-tutorial

Designing with progressive complexity, step-by-step in Framer.
JavaScript
1
star
64

react-use-three

React Hooks for three.js
TypeScript
1
star
65

exp-apollo-hooks-todo

Apollo's todo list example with Apollo hooks.
JavaScript
1
star
66

docs-sites

Collection of small docs sites.
JavaScript
1
star
67

ds-docs-starter

A starter for design system documentation.
JavaScript
1
star
68

component-preview

A micro storybook-like environment for previewing components.
TypeScript
1
star
69

framer-loupe-data

Nice website for designing with data at Framer Loupe.
JavaScript
1
star