joakin/elm-canvas/2.1.1

NOTE: the latest version is 5.0.0

Canvas

This module exposes a low level drawing API to work with the DOM canvas.

See instructions in the main page of the package for installation, as it requires a web component.

WARNING: This library is in development and right now it only exposes a low-level API that mirrors the DOM API, providing a bit of extra type safety where it makes sense. The DOM API is highly stateful and side-effectful, so be careful. To understand how to use this library for now, please familiarize yourself with the MDN Canvas Tutorial. We will be iterating on the design of the library to make it nicer and provide better defaults as time goes by, and make specific tutorials with Elm.

Usage in HTML

element : Int -> Int -> List (Attribute msg) -> Commands -> Html msg

Create a Html element that you can use in your view.

view : Model -> Html Msg
view { isRunning, time } =
    Canvas.element
        width
        height
        [ onClick ToggleRunning ]
        (Canvas.empty
            |> Canvas.clearScreen
            |> Canvas.fillStyle (Color.rgba 0 0 0 1)
            |> Canvas.fillRect 0 0 40 50
        )

Composing Commands

Represents commands to execute on the DOM canvas. You build commands with the helper functions the library exposes, which mirror the canvas API.

Then, you pass the commands to the element you render on the view, and they will be run!

Create an empty set of commands to start working with.

Canvas.empty
    |> Canvas.clearScreen
    |> Canvas.fillStyle (Color.rgba 0 0 0 1)
    |> Canvas.fillRect 0 0 40 50

Colors

Specifies the color or style to use inside shapes. The default is #000 (black). MDN Docs

empty |> fillStyle (Color.rgba 125 200 255 0.6)

Specifies the color or style to use for the lines around shapes. The default is #000 (black). MDN docs

empty
    |> strokeStyle (Color.rgb 0 0 255)
    |> strokeRect 10 10 100 100

Text

font : String -> Commands -> Commands

Specifies the current text style being used when drawing text. This string uses the same syntax as the CSS font specifier. The default font is 10px sans-serif. MDN docs

empty
    |> font "48px serif"
    |> strokeText "Hello world" 50 100
= Left
| Right
| Center
| Start
| End

Type of text alignment

  • Left
    • The text is left-aligned.
  • Right
    • The text is right-aligned.
  • Center
    • The text is centered.
  • Start
    • The text is aligned at the normal start of the line (left-aligned for left-to-right locales, right-aligned for right-to-left locales).
  • End
    • The text is aligned at the normal end of the line (right-aligned for left-to-right locales, left-aligned for right-to-left locales).

Specifies the current text alignment being used when drawing text. Beware that the alignment is based on the x value of the fillText command. So if textAlign is Center, then the text would be drawn at x - (width / 2).

The default value is Start. MDN docs

empty
    |> font "48px serif"
    |> textAlign Left
    |> strokeText "Hello world" 0 100
= Top
| Hanging
| Middle
| Alphabetic
| Ideographic
| Bottom

Type of text baseline.

  • Top
    • The text baseline is the top of the em square.
  • Hanging
    • The text baseline is the hanging baseline. (Used by Tibetan and other Indic scripts.)
  • Middle
    • The text baseline is the middle of the em square.
  • Alphabetic
    • The text baseline is the normal alphabetic baseline.
  • Ideographic
    • The text baseline is the ideographic baseline; this is the bottom of the body of the characters, if the main body of characters protrudes beneath the alphabetic baseline. (Used by Chinese, Japanese and Korean scripts.)
  • Bottom
    • The text baseline is the bottom of the bounding box. This differs from the ideographic baseline in that the ideographic baseline doesn't consider descenders.

Specifies the current text baseline being used when drawing text.

The default value is Alphabetic.

See MDN docs for examples and rendering of the different modes.

fillText : String -> Float -> Float -> Maybe Float -> Commands -> Commands

Draws a text string at the specified coordinates, filling the string's characters with the current foreground color. An optional parameter allows specifying a maximum width for the rendered text, which the user agent will achieve by condensing the text or by using a lower font size.

The text is rendered using the font and text layout configuration as defined by the font, textAlign, textBaseline, and direction properties.

To draw the outlines of the characters in a string, call the context's strokeText method.

empty |> fillText text x y maybeMaxWidth

MDN docs

empty
    |> font "48px serif"
    |> fillText "Hello world" 50 100 Nothing
strokeText : String -> Float -> Float -> Maybe Float -> Commands -> Commands

Strokes — that is, draws the outlines of — the characters of a specified text string at the given (x, y) position. If the optional fourth parameter for a maximum width is provided, the text is scaled to fit that width.

See the fillText method to draw the text with the characters filled with color rather than having just their outlines drawn.

empty |> strokeText text x y maybeMaxWidth

MDN docs

empty |> strokeText "Hello world" 40 50 (Just 100)

Shapes

fillRect : Float -> Float -> Float -> Float -> Commands -> Commands

Draws a filled rectangle whose starting point is at the coordinates (x, y) with the specified width and height and whose style is determined by the fillStyle attribute. MDN docs

empty |> fillRect x y width height
strokeRect : Float -> Float -> Float -> Float -> Commands -> Commands

Paints a rectangle which has a starting point at (x, y) and has a width and an height onto the canvas, using the current stroke style. MDN docs

empty |> strokeRect x y width height
clearRect : Float -> Float -> Float -> Float -> Commands -> Commands

Sets all pixels in the rectangle defined by starting point (x, y) and size (width, height) to transparent black, erasing any previously drawn content. MDN docs

empty |> clearRect x y width height

A common problem with clearRect is that it may appear it does not work when not using paths properly. Don't forget to call beginPath before starting to draw the new frame after calling clearRect.

fillCircle : Float -> Float -> Float -> Commands -> Commands

This is a helper non-standard method to fill a circle. Normally, you'd need to call beginPath, arc with the correct arguments, and fill. This is a convenience function to easily fill a circle that mirrors fillRect.

empty |> fillCircle x y radius
strokeCircle : Float -> Float -> Float -> Commands -> Commands

This is a helper non-standard method to stroke a circle. Normally, you'd need to call beginPath, arc with the correct arguments, and stroke. This is a convenience function to easily fill a circle that mirrors strokeRect.

empty |> strokeCircle x y radius

Paths

Starts a new path by emptying the list of sub-paths. Call this method when you want to create a new path. MDN docs

Causes the point of the pen to move back to the start of the current sub-path. It tries to add a straight line (but does not actually draw it) from the current point to the start. If the shape has already been closed or has only one point, this function does nothing. MDN docs

empty
    |> beginPath
    |> moveTo 20 20
    |> lineTo 200 20
    |> lineTo 120 120
    |> closePath
    -- draws last line of the triangle
    |> stroke
= NonZero
| EvenOdd

Type that represents the algorithm by which to determine if a point is inside a path or outside a path. If you are not sure, use NonZero as it is the default in the DOM API.

Fills the current or given path with the current fill style using the non-zero or even-odd winding rule. See type FillRule. MDN docs

Turns the path currently being built into the current clipping path. MDN docs

Note: Be aware that clip only works with shapes added to the path; it doesn't work with shape primitives such as rectangles created with fillRect. In this case you'd have to use rect to draw a rectangular path shape to be clipped.

Strokes the current or given path with the current stroke style using the non-zero winding rule. MDN docs

arc : Float -> Float -> Float -> Float -> Float -> Bool -> Commands -> Commands

Adds an arc to the path which is centered at (x, y) position with radius starting at startAngle and ending at endAngle going in the given direction by anticlockwise (False is clockwise). MDN docs

empty
    |> beginPath
    |> arc x y radius startAngle endAngle anticlockwise
    |> stroke
arcTo : Float -> Float -> Float -> Float -> Float -> Commands -> Commands

Adds an arc to the path with the given control points and radius.

The arc drawn will be a part of a circle, never elliptical. Typical use could be making a rounded corner.

One way to think about the arc drawn is to imagine two straight segments, from the starting point (latest point in current path) to the first control point, and then from the first control point to the second control point. These two segments form a sharp corner with the first control point being in the corner. Using arcTo, the corner will instead be an arc with the given radius.

The arc is tangential to both segments, which can sometimes produce surprising results, e.g. if the radius given is larger than the distance between the starting point and the first control point.

If the radius specified doesn't make the arc meet the starting point (latest point in the current path), the starting point is connected to the arc with a straight line segment.

empty |> arcTo x1 y1 x2 y2 radius

MDN docs

bezierCurveTo : Float -> Float -> Float -> Float -> Float -> Float -> Commands -> Commands

Adds a cubic Bézier curve to the path. It requires three points. The first two points are control points and the third one is the end point. The starting point is the last point in the current path, which can be changed using moveTo before creating the Bézier curve. MDN docs

bezierCurveTo cp1x cp1y cp2x cp2y x y
  • cp1x
    • The x axis of the coordinate for the first control point.
  • cp1y
    • The y axis of the coordinate for the first control point.
  • cp2x
    • The x axis of the coordinate for the second control point.
  • cp2y
    • The y axis of the coordinate for the second control point.
  • x
    • The x axis of the coordinate for the end point.
  • y
    • The y axis of the coordinate for the end point.
lineTo : Float -> Float -> Commands -> Commands

Connects the last point in the sub-path to the x, y coordinates with a straight line (but does not actually draw it). MDN docs

empty |> lineTo x y
moveTo : Float -> Float -> Commands -> Commands

Moves the starting point of a new sub-path to the (x, y) coordinates. MDN docs

empty |> moveTo x y
quadraticCurveTo : Float -> Float -> Float -> Float -> Commands -> Commands

Adds a quadratic Bézier curve to the path. It requires two points. The first point is a control point and the second one is the end point. The starting point is the last point in the current path, which can be changed using moveTo before creating the quadratic Bézier curve. MDN docs

empty |> quadraticCurveTo cpx cpy x y
  • cpx
    • The x axis of the coordinate for the control point.
  • cpy
    • The y axis of the coordinate for the control point.
  • x
    • The x axis of the coordinate for the end point.
  • y
    • The y axis of the coordinate for the end point.
rect : Float -> Float -> Float -> Float -> Commands -> Commands

Creates a path for a rectangle at position (x, y) with a size that is determined by width and height. Those four points are connected by straight lines and the sub-path is marked as closed, so that you can fill or stroke this rectangle. MDN docs

empty |> rect x y width height

Line settings

type LineCap
= ButtCap
| RoundCap
| SquareCap

Type of end points for line drawn.

  • ButtCap
    • The ends of lines are squared off at the endpoints.
  • RoundCap
    • The ends of lines are rounded.
  • SquareCap
    • The ends of lines are squared off by adding a box with an equal width and half the height of the line's thickness.

Determines how the end points of every line are drawn. See LineCap for the possible types. By default this property is set to ButtCap. MDN docs

empty
    |> beginPath
    |> moveTo 0 0
    |> lineWidth 15
    |> lineCap RoundCap
    |> lineTo 100 100
    |> stroke

Sets the line dash pattern offset or "phase". MDN docs

empty
    |> setLineDash [ 4, 16 ]
    |> lineDashOffset 2
    |> beginPath
    |> moveTo 0 100
    |> lineTo 400 100
    |> stroke
= BevelJoin
| RoundJoin
| MiterJoin

Determines how two connecting segments with non-zero lengths in a shape are joined together. MDN docs

  • Round
    • Rounds off the corners of a shape by filling an additional sector of disc centered at the common endpoint of connected segments. The radius for these rounded corners is equal to the line width.
  • Bevel
    • Fills an additional triangular area between the common endpoint of connected segments, and the separate outside rectangular corners of each segment.
  • Miter
    • Connected segments are joined by extending their outside edges to connect at a single point, with the effect of filling an additional lozenge-shaped area. This setting is affected by the miterLimit property.

Sets how two connecting segments (of lines, arcs or curves) with non-zero lengths in a shape are joined together (degenerate segments with zero lengths, whose specified endpoints and control points are exactly at the same position, are skipped). See the type LineJoin.

By default this property is set to MiterJoin. Note that the lineJoin setting has no effect if the two connected segments have the same direction, because no joining area will be added in this case.

MDN docs

empty
    |> lineWidth 10
    |> lineJoin RoundJoin
    |> beginPath
    |> moveTo 0 0
    |> lineTo 200 100
    |> lineTo 300 0
    |> stroke

Sets the thickness of lines in space units. When setting, zero, negative, Infinity and NaN values are ignored; otherwise the current value is set to the new value. MDN docs

empty
    |> beginPath
    |> moveTo 0 0
    |> lineWidth 15
    |> lineTo 100 100
    |> stroke

Sets the miter limit ratio in space units. When setting, zero, negative, Infinity and NaN values are ignored; otherwise the current value is set to the new value. MDN docs

setLineDash : List Float -> Commands -> Commands

Sets the line dash pattern used when stroking lines, using an array of values which specify alternating lengths of lines and gaps which describe the pattern.

To return to using solid lines, set the line dash list to an empty array.

empty |> setLineDash segments
  • segments
    • An Array of numbers which specify distances to alternately draw a line and a gap (in coordinate space units). If the number of elements in the array is odd, the elements of the array get copied and concatenated. For example, [5, 15, 25] will become [5, 15, 25, 5, 15, 25]. If the array is empty, the line dash list is cleared and line strokes return to being solid.

MDN docs

Shadows

Specifies the level of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix. The default value is 0. Negative, Infinity or NaN values are ignored. Note that shadows are only drawn, if the shadowColor property is set to a non-transparent value. MDN docs

empty
    |> shadowColor (Color.rgb 0 0 0)
    |> shadowBlur 10
    |> fillStyle (Color.rgb 255 255 255)
    |> fillRect 10 10 100 100

Specifies the color of the shadow. MDN docs

Note that shadows are only drawn, if the shadowColor property is set (non-transparent) and either the shadowBlur, the shadowOffsetX, or the shadowOffsetY property are non-zero.

empty
    |> shadowColor (Color.rgb 0 0 0)
    |> shadowOffsetY 10
    |> shadowOffsetX 10
    |> fillStyle (Color.rgb 0 255 0)
    |> fillRect 10 10 100 100

Specifies the distance that the shadow will be offset in horizontal distance. MDN docs

The default value is 0. Infinity or NaN values are ignored.

empty
    |> shadowColor (Color.rgb 0 0 0)
    |> shadowOffsetY 10
    |> shadowOffsetX 10
    |> fillStyle (Color.rgb 0 255 0)
    |> fillRect 10 10 100 100

Specifies the distance that the shadow will be offset in vertical distance. MDN docs

The default value is 0. Infinity or NaN values are ignored.

empty
    |> shadowColor (Color.rgb 0 0 0)
    |> shadowOffsetY 10
    |> shadowOffsetX 10
    |> fillStyle (Color.rgb 0 255 0)
    |> fillRect 10 10 100 100

Global Canvas settings

Specifies the alpha value that is applied to shapes and images before they are drawn onto the canvas. The value is in the range from 0.0 (fully transparent) to 1.0 (fully opaque). The default value is 1.0. Values outside the range, including Infinity and NaN will not be set and globalAlpha will retain its previous value.

See also the chapter Applying styles and color. MDN docs

-- Drawing two transparent rectangles
empty
    |> globalAlpha 0.5
    |> fillStyle (Color.rgb 0 0 255)
    |> fillRect 10 10 100 100
    |> fillStyle (Color.rgb 255 0 0)
    |> fillRect 50 50 100 100
= SourceOver
| SourceIn
| SourceOut
| SourceAtop
| DestinationOver
| DestinationIn
| DestinationOut
| DestinationAtop
| Lighter
| Copy
| Xor
| Multiply
| Screen
| Overlay
| Darken
| Lighten
| ColorDodge
| ColorBurn
| HardLight
| SoftLight
| Difference
| Exclusion
| Hue
| Saturation
| Color
| Luminosity

Type of compositing operation, identifying which of the compositing or blending mode operations to use. See the chapter Compositing from the Canvas Tutorial.

For more information and pictures of what each mode does, see the MDN docs.

Sets the type of compositing operation to apply when drawing new shapes, where type is a GlobalCompositeOperationMode identifying which of the compositing or blending mode operations to use.

See the chapter Compositing from the Canvas Tutorial, or visit the MDN docs for more information and pictures of what each mode does.

empty |> globalCompositeOperation Screen

Saves the entire state of the canvas by pushing the current state onto a stack. MDN docs

The drawing state that gets saved onto a stack consists of:

  • The current transformation matrix.
  • The current clipping region.
  • The current dash list.
  • The current values of the following attributes: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled.

Restores the most recently saved canvas state by popping the top entry in the drawing state stack. If there is no saved state, this method does nothing. MDN docs

Global Canvas transforms

rotate : Float -> Commands -> Commands

Adds a rotation to the transformation matrix. The angle argument represents a clockwise rotation angle and is expressed in radians.

empty |> rotate (degrees 90)

The rotation center point is always the canvas origin. To change the center point, we will need to move the canvas by using the translate method.

MDN docs

scale : Float -> Float -> Commands -> Commands

Adds a scaling transformation to the canvas units by x horizontally and by y vertically.

By default, one unit on the canvas is exactly one pixel. If we apply, for instance, a scaling factor of 0.5, the resulting unit would become 0.5 pixels and so shapes would be drawn at half size. In a similar way setting the scaling factor to 2.0 would increase the unit size and one unit now becomes two pixels. This results in shapes being drawn twice as large.

empty |> scale x y
  • x
    • Scaling factor in the horizontal direction.
  • y
    • Scaling factor in the vertical direction.

Note: You can use scale -1 1 to flip the context horizontally and scale 1 -1 to flip it vertically.

MDN docs

translate : Float -> Float -> Commands -> Commands

Adds a translation transformation by moving the canvas and its origin x horizontally and y vertically on the grid. MDN docs

empty |> translate x y
transform : Float -> Float -> Float -> Float -> Float -> Float -> Commands -> Commands

Multiplies the current transformation with the matrix described by the arguments of this method. You are able to scale, rotate, move and skew the context.

See also the setTransform method which resets the current transform to the identity matrix and then invokes transform.

empty |> transform a b c d e f
  • a (m11)
    • Horizontal scaling.
  • b (m12)
    • Horizontal skewing.
  • c (m21)
    • Vertical skewing.
  • d (m22)
    • Vertical scaling.
  • e (dx)
    • Horizontal moving.
  • f (dy)
    • Vertical moving.

MDN docs

setTransform : Float -> Float -> Float -> Float -> Float -> Float -> Commands -> Commands

Resets (overrides) the current transformation to the identity matrix and then invokes a transformation described by the arguments of this method.

See also the transform method, which does not override the current transform matrix and multiplies it with a given one.

empty |> setTransform a b c d e f
  • a (m11)
    • Horizontal scaling.
  • b (m12)
    • Horizontal skewing.
  • c (m21)
    • Vertical skewing.
  • d (m22)
    • Vertical scaling.
  • e (dx)
    • Horizontal moving.
  • f (dy)
    • Vertical moving.

MDN docs