Easel lets you build Canvas 2D drawing operations as data.
Create a canvas, pipe it through drawing functions to build up a list of operations, then render to a backend (browser via LiveView, native window via wx, or consume the ops list directly).
All Canvas 2D API functions are available directly on this module as
snake_cased versions of their JavaScript counterparts. Use set/3
and call/3 for properties or methods not yet generated.
Example
canvas =
Easel.new(300, 300)
|> Easel.set_fill_style("blue")
|> Easel.fill_rect(0, 0, 100, 100)
|> Easel.set_line_width(10)
|> Easel.stroke_rect(100, 100, 100, 100)
|> Easel.render()The resulting %Easel{} struct contains an ops list that maps
directly to Canvas 2D API calls:
canvas.ops
#=> [["set", ["fillStyle", "blue"]], ["fillRect", [0, 0, 100, 100]], ...]Templates and Instances
For scenes with many similar shapes, define a template once and stamp out instances with per-instance transforms:
canvas =
Easel.new(800, 600)
|> Easel.template(:particle, fn c ->
c |> Easel.begin_path() |> Easel.arc(0, 0, 3, 0, 6.28) |> Easel.fill()
end)
|> Easel.instances(:particle, [
%{x: 100, y: 200, fill: "red"},
%{x: 300, y: 400, fill: "blue", alpha: 0.5}
])
|> Easel.render()The LiveView hook renders instances client-side (template ops cached,
only instance data sent per frame). For other backends, call expand/1
to flatten into plain ops.
Backends
Easel.LiveView- Phoenix LiveView component with colocated JS hookEasel.WX- Native desktop window via Erlang's:wx(wxWidgets)- Custom - consume
canvas.opsdirectly in your own renderer
Summary
Functions
Calls a Canvas 2D context method with the given arguments.
Expands __instances ops into plain Canvas 2D ops.
Draws instances of a previously defined template.
Creates a new canvas with no dimensions set.
Creates a new canvas with the given width and height.
Pushes a raw operation onto the canvas.
Finalizes the canvas by reversing the ops list into execution order.
Sets a Canvas 2D context property.
Defines a reusable drawing template.
Sets template-level instance options for this canvas.
Functions
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arcTo
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo
Calls a Canvas 2D context method with the given arguments.
Easel.call(canvas, "fillRect", [0, 0, 100, 100])
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/closePath
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createImageData
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createRadialGradient
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawFocusIfNeeded
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse
Expands __instances ops into plain Canvas 2D ops.
The LiveView hook handles instances natively on the client (more efficient), but other backends (wx, custom) can call this to get a flat ops list that any Canvas 2D renderer can execute.
Automatically calls render/1 first if needed.
Example
canvas
|> Easel.template(:dot, fn c -> ... end)
|> Easel.instances(:dot, [%{x: 10, y: 20}])
|> Easel.expand()
# ops now contain save/translate/rotate/.../restore sequences
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getLineDash
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getTransform
Draws instances of a previously defined template.
Each instance is a map that may contain:
:x,:y- translation (default0,0):rotate- rotation in radians (default0):scale_x,:scale_y- scale factors (default1,1):fill- fill style override (applied before template ops):stroke- stroke style override:alpha- global alpha override
The hook renders each instance via save → translate → rotate → scale → [style overrides] → [template ops] → restore.
You can optionally quantize float values before serialization by passing
precision globally or per field:
Easel.instances(canvas, :boid, instances, precision: 2)
Easel.instances(canvas, :boid, instances, x: 1, y: 1, rotate: 3)Example
canvas
|> Easel.instances(:boid, Enum.map(boids, fn b ->
%{x: b.x, y: b.y, rotate: :math.atan2(b.vy, b.vx),
fill: "hsl(#{hue}, 70%, 60%)"}
end))
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInStroke
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineTo
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/measureText
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/moveTo
Creates a new canvas with no dimensions set.
Creates a new canvas with the given width and height.
Pushes a raw operation onto the canvas.
Operations are stored in reverse order for efficient prepend.
Call render/1 to finalize the ops list into correct order.
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rect
Finalizes the canvas by reversing the ops list into execution order.
Must be called before passing the canvas to a backend for rendering. Safe to call multiple times - subsequent calls are no-ops.
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/resetTransform
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rotate
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale
Sets a Canvas 2D context property.
Easel.set(canvas, "fillStyle", "blue")
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/miterLimit
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/stroke
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeRect
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeText
Defines a reusable drawing template.
A template is a named set of ops that can be instantiated many times
with different transforms. The template function receives a fresh
%Easel{} and should return one with ops added (don't call render/1).
Example
canvas =
Easel.new(800, 600)
|> Easel.template(:boid, fn c ->
c
|> Easel.begin_path()
|> Easel.move_to(12, 0)
|> Easel.line_to(-4, -5)
|> Easel.line_to(-4, 5)
|> Easel.close_path()
|> Easel.fill()
end)
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate
Sets template-level instance options for this canvas.
Useful when templates are prepared in one canvas and instances are emitted from another (for example, static templates cached in assigns).