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

@moyotsukai/bezier

v1.0.1

Published

A tool for drawing bezier curves.

Downloads

10

Readme

@moyotsukai/bezier

A tool for drawing bezier curves.
This library is for React projects in local environments.

Quick Start

npm i @moyotsukai/bezier   
import Bezier from '@moyotsukai/bezier'

const App: React.FC = () => {
  const path = Bezier.spline({
    start: { x: 100, y: 400 },
    points: [
      {
        end: { eaa: 15, eal: 400 },
        controls: { sca: 30, scl: 100, eca: 45, ecl: 120 }
      }
    ]
  })

  return (
    <Bezier.Root>
      <Bezier.Svg
        splines={[path]}
      />
    </Bezier.Root>
  )
}

export default App

Drawing Bezier Curves

A bezier curve consists of the following four points.

four_points

Defining the Start Point

Give the coordinate to define the start point.

const CENTER: Bezier.Vec2 = { x: 400, y: 300 }

const path = Bezier.spline({
    start: CENTER,
    ...
  })

start_point

Defining the End Point

Option 1: Give the coordinate.

const path = Bezier.spline({
    start: CENTER,
    points: [
      {
        end: { x: 600, y: 100 },
        ...
      }
    ]
  })

end_point


Option 2: Define the end point using end-anchor-angle (eaa) and end-anchor-length (eal).

const path = Bezier.spline({
    start: CENTER,
    points: [
      {
        end: { eaa: 35, eal: 300 },
        ...
      }
    ]
  })

end_point

Defining Control Points

Option 1: Give the coordinate for start-control (sc) and end-control (ec).

const path = Bezier.spline({
  start: CENTER,
  points: [
    {
      end: { eaa: 35, eal: 300 },
      controls: { sc: { x: 450, y: 120 }, ec: { x: 550, y: 90 } }
    }
  ]
})

end_point


Option 2: Define the control points using start-control-angle (sca), start-control-length (scl), end-control-angle (eca), and end-control-length (ecl).

const path = Bezier.spline({
  start: CENTER,
  points: [
    {
      end: { eaa: 35, eal: 300 },
      controls: { sca: 30, scl: 200, eca: 50, ecl: 100 }
    }
  ]
})

end_point


Option 3: Define the control points using control-midpoint-angle (cma), control-midpoint-length (cml), ratio of control-distance to end-anchor-length (cdr), and control-distance-angle (cda).

const path = Bezier.spline({
  start: CENTER,
  points: [
    {
      end: { eaa: 35, eal: 800 * SCALE },
      controls: { cma: 30, cml: 120, cdr: 0.3, cda: -15 }
    }
  ]
})

end_point end_point end_point

API Reference

Bezier.Vec2

type Vec2 = {
  x: number
  y: number
}

Bezier.Points

type Points = BezierPoints

type BezierPoints = {
  startAnchor: Vec2
  startControl: Vec2,
  endControl: Vec2,
  endAnchor: Vec2,
  anchorMidpoint: Vec2,
  controlMidpoint: Vec2
}

Bezier.Spline

type Spline = BezierSpline

class BezierSpline {
    private _paths
    private _stroke
    private _fill

    constructor(paths: BezierPoints[], style?: BezierStyleProps)

    get paths(): BezierPoints[]
    get stroke(): string | null
    get fill(): string | null
    get startAnchor(): Vec2
    get endAnchor(): Vec2

    rotate({ center, angle }: {
        center: Vec2
        angle: number
    }): BezierSpline

    mirror({ center, angle }: {
        center: Vec2
        angle: number
    }): BezierSpline

    translate({ angle, distance }: {
        angle: number
        distance: number
    }): BezierSpline
}

Bezier.spline()

function spline(props: ControlPointsProps, style?: StyleProps): BezierSpline

Bezier.ControlPointsProps

type ControlPointsProps = BezierControlPointsProps

type BezierControlPointsProps = {
  start: Vec2,
  points: {
    end: EndPointAngleParameters | Vec2,
    controls: ControlPointsAngleParameters | ControlPointsMidpointParameters | ControlPointsVec2Parameters
  }[]
}

//eaa: end anchor angle
//eal: end anchor length
type EndPointAngleParameters = {
  eaa: number,
  eal: number
}

//sca: start control angle
//scl: start control length
//eca: end control angle
//ecl: end control length
type ControlPointsAngleParameters = {
  sca: number | "smooth"
  scl: number
  eca: number
  ecl: number
}

//cma: control midpoint angle
//cml: control midpoint length
//cdr: ratio of control distance to end anchor length
//cda: control distance angle
type ControlPointsMidpointParameters = {
  cma: number,
  cml: number,
  cdr: number | "smooth",
  cda: number
}

//sc: start control point
//ec: end control point
type ControlPointsVec2Parameters = {
  sc: Vec2,
  ec: Vec2
}

Bezier.StyleProps

type StyleProps = BezierStyleProps

type BezierStyleProps = {
  stroke?: string | null
  fill?: string | null
}

<Bezier.Root>

Props

{
  fileName?: string
  children: React.ReactNode
}

<Bezier.Svg />

Props

{
  splines: BezierSpline[],
  width?: number,
  height?: number,
  expandCanvasToEdge?: boolean,
  shouGuide?: boolean
}

Bezier.getStartAnchor()

function getStartAnchor(paths: BezierPoints[]): Vec2

Bezier.getEndAnchor()

function getEndAnchor(paths: BezierPoints[]): Vec2

Bezier.mirrorPath()

function mirrorPath({
  center: Vec2, 
  angle: number, 
  path: BezierPoints[]
}): BezierPoints[]

Bezier.rotatePath()

function rotatePath({ 
  center: Vec2,
   angle: number,
   path: BezierPoints[]
}): BezierPoints[]

Bezier.translatePath()

function translatePath({ 
  angle: number, 
  distance: number, 
  path: BezierPoints[]
}): BezierPoints[] 

Bezier.absoluteAngle()

function absoluteAngle({
  start: Vec2,
  end: Vec2 
}): number

Bezier.distance()

function distance(a: Vec2, b: Vec2): number

Bezier.inferLine()

function inferLine({ 
  point: Vec2, 
  angle: number 
}): [Vec2, Vec2]

Bezier.intersection()

function intersection(ab: [Vec2, Vec2], cd: [Vec2, Vec2]): Vec2 | null

Bezier.midpoint()

function midpoint(a: Vec2, b: Vec2): Vec2

Example

import Bezier from '@moyotsukai/bezier'

const NUM = 8
const CENTER: Bezier.Vec2 = { x: 400, y: 300 }
const SCALE = 0.3

const Example: React.FC = () => {
  const path_1 = Bezier.spline({
    start: { x: CENTER.x + 5, y: CENTER.y - 25 },
    points: [
      {
        end: { eaa: 90, eal: 800 * SCALE },
        controls: { cma: -60, cml: -200 * SCALE, cdr: 0.3, cda: 60 }
      }
    ]
  }, {
    stroke: "red"
  })

  const path_2 = Bezier.spline({
    start: { x: CENTER.x - 5, y: CENTER.y - 25 },
    points: [
      {
        end: { eaa: 85, eal: 500 * SCALE },
        controls: { cma: -30, cml: -50 * SCALE, cdr: 0.5, cda: 30 }
      },
      {
        end: { eaa: 130, eal: 300 * SCALE },
        controls: { sca: "smooth", scl: 120 * SCALE, eca: -30, ecl: 80 * SCALE }
      }
    ]
  }, {
    stroke: "blue"
  })

  const path_3 = Bezier.spline({
    start: path_1.endAnchor,
    points: [
      {
        end: path_2.endAnchor,
        controls: { sca: 0, scl: 0, eca: 0, ecl: 0 }
      }
    ]
  })

  const splines: Bezier.Spline[] = Array(NUM).fill(0).map((_, index) => {
    return [
      path_1.rotate({ center: CENTER, angle: 360 / NUM * index }),
      path_2.rotate({ center: CENTER, angle: 360 / NUM * index }),
      path_3.rotate({ center: CENTER, angle: 360 / NUM * index }),
      Bezier.spline({
        start: path_2.rotate({ center: CENTER, angle: 360 / NUM * index }).endAnchor,
        points: [
          {
            end: path_1.rotate({ center: CENTER, angle: 360 / NUM * (index + 1) }).endAnchor,
            controls: { sca: 0, scl: 0, eca: 0, ecl: 0 }
          }
        ]
      })
    ]
  }).flat()

  return (
    <Bezier.Svg
      splines={splines}
      expandCanvasToEdge={true}
    />
  )
}

export default Example

example_1_svg