A general-purpose library for working with curves and paths.
The primary aim is SVG paths, but the types and functions in this package can also be used for animations or other graphics backends (webgl, canvas).
Additionally, this package is meant to serve as an interchange format between packages.
MoveTo moves the cursorDrawTo draws a curveLines can be composed in two "obvious" ways: concatenation and layering.
concatenation happens on the subpath level, using the functions
connect: draws a straight line connecting two subpaths (end to start)continue: make the start and end point of two subpaths coincidecontinueSmooth: make the start and end point of two subpaths coincide, and rotate to make the transition smooth.SubPaths can be layered by putting them in a list, forming a Path.
Ideally, you can use the drawing functions in Curve and use the composition in SubPath and Path, then use either SubPath.element or Path.element to create svg.
import SubPath exposing SubPath
import Curve
import Svg exposing (Svg)
import Svg.Attributes exposing (width, height, viewBox, fill, stroke)
hShape : SubPath
hShape =
Curve.linearClosed
[ ( 0.3, 0.2 )
, ( 0.4, 0.2 )
, ( 0.4, 0.45 )
, ( 0.6, 0.45 )
, ( 0.6, 0.2 )
, ( 0.7, 0.2 )
, ( 0.7, 0.8 )
, ( 0.6, 0.8 )
, ( 0.6, 0.55 )
, ( 0.4, 0.55 )
, ( 0.4, 0.8 )
, ( 0.3, 0.8 )
]
logo : Svg msg
logo =
Svg.svg [ width "50", height "50", viewBox "0 0 1 1" ]
[ SubPath.element hShape [ fill "none", stroke "black" ] ] Existing svg path strings can be parsed into a nice elm data structure
import Path
import SubPath
pathAsString =
"""
M 213.1,6.7
c -32.4-14.4-73.7,0-88.1,30.6
C 110.6,4.9,67.5-9.5,36.9,6.7
C 2.8,22.9-13.4,62.4,13.5,110.9
C 33.3,145.1,67.5,170.3,125,217
c 59.3-46.7,93.5-71.9,111.5-106.1
C 263.4,64.2,247.2,22.9,213.1,6.7
z
"""
myPath =
SubPath.subpath (MoveTo ( 213.1, 6.7 ))
[ CurveTo
[ ( ( 110.6, 4.9 ), ( 67.5, -9.5 ), ( 36.9, 6.7 ) )
, ( ( 4.5, -7.7 ), ( -36.800000000000004, 6.7 ), ( -51.199999999999996, 37.300000000000004 ) )
, ( ( 110.6, 4.9 ), ( 67.5, -9.5 ), ( 36.9, 6.7 ) )
, ( ( 2.8, 22.9 ), ( -13.4, 62.4 ), ( 13.5, 110.9 ) )
, ( ( 33.3, 145.1 ), ( 67.5, 170.3 ), ( 125, 217 ) )
, ( ( 184.3, 170.3 ), ( 218.5, 145.1 ), ( 236.5, 110.9 ) )
, ( ( 263.4, 64.2 ), ( 247.2, 22.9 ), ( 213.1, 6.7 ) )
]
, ClosePath
]
Path.parse pathAsString
|> Result.toMaybe
|> Maybe.andThen List.head
|> Maybe.withDefault SubPath.empty
|> SubPath.compress
--> myPathThe Segment module breaks down a line into four basic segment types, and exposes some mathematical functions (and the constructors, if you want to define your own fancy stuff).
The LowLevel.Command module contains individual instructions. These should only be used for building other primitives! Making and combining curves should happen on the SubPath level.
That's not part of this package, but I'm looking into it. The julia Compose.jl library has some interesting ideas.