Easel (easel v0.2.2)

Copy Markdown View Source

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 hook
  • Easel.WX - Native desktop window via Erlang's :wx (wxWidgets)
  • Custom - consume canvas.ops directly 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

arc(ctx, x, y, radius, start_angle, end_angle)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc

arc(ctx, x, y, radius, start_angle, end_angle, anticlockwise)

arc_to(ctx, x1, y1, x2, y2, radius)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arcTo

begin_path(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath

bezier_curve_to(ctx, cp1x, cp1y, cp2x, cp2y, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo

call(ctx, op, arguments)

Calls a Canvas 2D context method with the given arguments.

Easel.call(canvas, "fillRect", [0, 0, 100, 100])

clear_rect(ctx, x, y, w, h)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect

clip(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip

clip(ctx, winding)

clip(ctx, path, winding)

close_path(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/closePath

create_image_data(ctx, imagedata)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createImageData

create_image_data(ctx, sw, sh)

create_linear_gradient(ctx, x0, y0, x1, y1)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient

create_pattern(ctx, image, repetition)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern

create_radial_gradient(ctx, x0, y0, r0, x1, y1, r1)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createRadialGradient

draw_focus_if_needed(ctx, element)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawFocusIfNeeded

draw_image(ctx, image, dx, dy)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

draw_image(ctx, image, dx, dy, dw, dh)

draw_image(ctx, image, sx, sy, sw, sh, dx, dy, dw, dh)

ellipse(ctx, x, y, radius_x, radius_y, rotation, start_angle, end_angle)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse

ellipse(ctx, x, y, radius_x, radius_y, rotation, start_angle, end_angle, anticlockwise)

expand(ctx)

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

fill(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill

fill(ctx, winding)

fill(ctx, path, winding)

fill_rect(ctx, x, y, w, h)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect

fill_text(ctx, text, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText

fill_text(ctx, text, x, y, max_width)

get_image_data(ctx, sx, sy, sw, sh)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData

get_line_dash(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getLineDash

get_transform(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getTransform

instances(ctx, name, instance_data, opts \\ [])

Draws instances of a previously defined template.

Each instance is a map that may contain:

  • :x, :y - translation (default 0, 0)
  • :rotate - rotation in radians (default 0)
  • :scale_x, :scale_y - scale factors (default 1, 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))

is_point_in_path(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath

is_point_in_path(ctx, x, y, winding)

is_point_in_path(ctx, path, x, y, winding)

is_point_in_stroke(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInStroke

is_point_in_stroke(ctx, path, x, y)

line_to(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineTo

measure_text(ctx, text)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/measureText

move_to(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/moveTo

new()

Creates a new canvas with no dimensions set.

new(width, height)

Creates a new canvas with the given width and height.

push_op(ctx, op)

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.

put_image_data(ctx, imagedata, dx, dy)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData

put_image_data(ctx, imagedata, dx, dy, dirty_x, dirty_y, dirty_width, dirty_height)

quadratic_curve_to(ctx, cpx, cpy, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo

rect(ctx, x, y, w, h)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rect

render(ctx)

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.

reset_transform(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/resetTransform

restore(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore

rotate(ctx, angle)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rotate

save(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save

scale(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale

set(ctx, key, val)

Sets a Canvas 2D context property.

Easel.set(canvas, "fillStyle", "blue")

set_fill_style(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle

set_filter(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter

set_font(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font

set_global_alpha(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha

set_global_composite_operation(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

set_image_smoothing_enabled(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled

set_line_cap(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineCap

set_line_dash(ctx, segments)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash

set_line_dash_offset(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset

set_line_join(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin

set_line_width(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth

set_miter_limit(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/miterLimit

set_shadow_blur(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur

set_shadow_color(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor

set_shadow_offset_x(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX

set_shadow_offset_y(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY

set_stroke_style(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle

set_text_align(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign

set_text_baseline(ctx, value)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline

set_transform(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform

set_transform(ctx, transform)

set_transform(ctx, a, b, c, d, e, f)

stroke(ctx)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/stroke

stroke(ctx, path)

stroke_rect(ctx, x, y, w, h)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeRect

stroke_text(ctx, text, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeText

stroke_text(ctx, text, x, y, max_width)

template(ctx, name, draw_fn, opts \\ [])

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)

transform(ctx, a, b, c, d, e, f)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform

translate(ctx, x, y)

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate

with_template_opts(ctx, opts_map)

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).