smooth-curve

Drawing smooth curve easily in a simple way, and what under the hood is also simple.

Usage no npm install needed!

<script type="module">
  import smoothCurve from 'https://cdn.skypack.dev/smooth-curve';
</script>

README

Smooth Curve

Drawing smooth curve easily in a simple way, and what under the hood is also simple.

Install

$ yarn add smooth-curve
# or
$ npm install --save smooth-curve

or

<script src="https://unpkg.com/smooth-curve/smooth-curve.min.js"></script>

Usage

Draw a smooth curve

Input canvas context which you want to draw on and key points

import SmoothCurve from 'smooth-curve'
const ctx = document.querySelector('canvas').getContext("2d");
let curves = [
  [
    {x:83,y:41,curve:true},
    {x:43,y:66,curve:true},
    {x:83,y:90,curve:true},
    {x:45,y:113,curve:true}
  ],[
    {x:147,y:39,curve:true},
    {x:118,y:50,curve:true},
    {x:107,y:74,curve:true},
    {x:120,y:100,curve:true},
    {x:146,y:111,curve:true}
  ]
]
curves.map(points => {
  SmoothCurve.draw(ctx, points)
})

smooth-curve

Draw a closed curve

Only need to set closed attribute to true in option parameter.

...
curves.map(points => {
  SmoothCurve.draw(ctx, points, { closed: true })
})

closed-curve

Set custom style

Only need to use style setting syntax before calling draw function.

...
ctx.lineWidth = 5
ctx.strokeStyle = 'rgb(50, 50, 255)'
curves.map(points => {
  SmoothCurve.draw(ctx, points)
})

custom-style

Set point's curve attribute

Change point's curve attribute to false and see what happened

...
let curves = [
  [
    {x:83,y:41,curve:true},
    {x:43,y:66,curve:true},
    {x:83,y:90,curve:false},
    {x:45,y:113,curve:true}
  ],[
    {x:147,y:39,curve:true},
    {x:118,y:50,curve:false},
    {x:107,y:74,curve:false},
    {x:120,y:100,curve:true},
    {x:146,y:111,curve:true}
  ]
]

curves.map(points => {
  SmoothCurve.draw(ctx, points)
})

false-point-curve

Use returned Path2D instance

draw() method would return a Path2D instance so you can use it to do some other processing.

...
let curvePath = SmoothCurve.draw(ctx, points)
OtherHandler(curvePath)

API

draw(context, points, option?)

  • context <CanvasRenderingContext2D>
  • points <CurvePoint[]>
    • CurvePoint <Object>
      • x <number> The x position of point
      • y <number> The y position of point
      • curve <boolean> If set to true, the tension of control points around this point will be 0.5. Otherwise the tension will be 0.
  • option <Object>
    • closed? <boolean> If set to true, the curve will be closed. It means the start and the end point will be connected by extra control points. Defaults to false.
    • tension? <number> This controls all the control points' position by adjusting the distance ratio between key points. The range is [0,1]. Defaults to 0.5.
  • returns: <Path2D | undefined>

getCurveControlPoints(points, option?)

  • points <CurvePoint[]> Same as points in draw() function
  • option <Object> Same as option in draw() function
  • returns: <Point[]>

Under the hood

  • Only use canvas inner APIs to draw quadratic and cubic bezier curves.
  • Use some simple steps to draw smooth curve through all key points.
  • 控制点计算方法中文资料

Related

This simple method is inspired by AGG. The author wrote:

"This method is pure heuristic and empiric. It probably gives a wrong result from the point of view of strict mathematical modeling. But in practice the result is good enough and it requires absolute minimum of calculations. "

Other spline curve related lib using more complicated interpolating method: