Plushie.Canvas.Shape (Plushie v0.6.0)

Copy Markdown View Source

Pure builder functions returning typed canvas shape structs.

Every function returns a struct from Plushie.Canvas.Shape.*. The Plushie.Encode protocol implementations on each struct handle wire-format conversion. These are plain functions, not macros -- they can be called anywhere.

Structure macros (group, layer) live in Plushie.UI and are available inside canvas do-blocks. Inside those blocks, text, image, and svg calls resolve automatically to their canvas shape variants. For helper functions outside canvas blocks, import this module directly.

When to import this module

Import Plushie.Canvas.Shape when you build shapes in standalone helper functions (defp) outside a Plushie.UI canvas block:

import Plushie.Canvas.Shape

defp draw_indicator(x, y, color) do
  [
    circle(x, y, 6, fill: color),
    circle(x, y, 3, fill: "#fff")
  ]
end

Inside Plushie.UI canvas/layer/group blocks, all shape functions are already in scope via import Plushie.UI -- no extra import needed.

Basic shapes

rect(10, 20, 100, 50, fill: "#ff0000")
circle(50, 50, 25, stroke: stroke("#000", 2))
line(0, 0, 100, 100, stroke: stroke("#333", 1, cap: "round"))
text(10, 10, "Hello", fill: "#000", size: 16)

Paths

path([move_to(0, 0), line_to(100, 0), line_to(50, 80), close()],
  fill: "#0088ff",
  stroke: stroke("#000", 2)
)

Transforms

Transform commands are interleaved with shapes in a layer's shape list:

[
  push_transform(),
  translate(100, 100),
  rotate(:math.pi() / 4),
  rect(0, 0, 50, 50, fill: "#f00"),
  pop_transform()
]

Clipping

Clip regions restrict drawing to a rectangular area:

[
  push_clip(10, 10, 100, 80),
  rect(0, 0, 200, 200, fill: "#ff0000"),
  pop_clip()
]

Clip regions nest -- inner clips are intersected with outer clips.

Per-shape opacity

All shapes (except SVG) accept an :opacity option (0.0-1.0) that multiplies into the fill and stroke color alpha channels:

rect(0, 0, 100, 100, fill: "#ff0000", opacity: 0.5)
circle(50, 50, 25, stroke: stroke("#000", 2), opacity: 0.3)

Text alignment

The text/4 builder accepts :align_x and :align_y options:

text(100, 50, "Centered", fill: "#000", align_x: "center", align_y: "center")

Valid values for :align_x: "left", "center", "right". Valid values for :align_y: "top", "center", "bottom".

Gradients

Use linear_gradient/3 as a fill value:

rect(0, 0, 200, 100,
  fill: linear_gradient({0, 0}, {200, 0}, [{0.0, "#ff0000"}, {1.0, "#0000ff"}])
)

Interactive shapes

Make shapes interactive by placing them in a named group with interaction opts:

group "btn", on_click: true, cursor: "pointer" do
  rect(0, 0, 100, 40, fill: "#3498db")
end

Summary

Functions

Arc path command (center, radius, start and end angles in radians).

Tangent arc path command.

Cubic bezier curve path command.

Builds a circle shape.

Create a clip rectangle for a group.

Close path command.

Draws a raster image on the canvas at the given position and size.

Builds a line shape.

Line-to path command.

Builds a linear gradient, usable as a fill value.

Move-to path command.

Builds an arbitrary path shape.

Quadratic bezier curve path command.

Builds a rectangle shape.

Create a rotation transform.

Rounded rectangle path command.

Create a uniform scale transform.

Create a non-uniform scale transform.

Builds a stroke descriptor.

Draws an SVG on the canvas at the given position and size.

Builds a text shape.

Create a translation transform.

Functions

arc(cx, cy, r, start_angle, end_angle)

@spec arc(
  cx :: number(),
  cy :: number(),
  r :: number(),
  start_angle :: number(),
  end_angle :: number()
) :: list()

Arc path command (center, radius, start and end angles in radians).

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

@spec arc_to(
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  radius :: number()
) :: list()

Tangent arc path command.

bezier_to(cp1x, cp1y, cp2x, cp2y, x, y)

@spec bezier_to(
  cp1x :: number(),
  cp1y :: number(),
  cp2x :: number(),
  cp2y :: number(),
  x :: number(),
  y :: number()
) :: list()

Cubic bezier curve path command.

circle(x, y, r, opts \\ [])

@spec circle(x :: number(), y :: number(), r :: number(), opts :: keyword()) ::
  Plushie.Canvas.Shape.Circle.t()

Builds a circle shape.

clip(x, y, w, h)

@spec clip(x :: number(), y :: number(), w :: number(), h :: number()) ::
  Plushie.Canvas.Shape.Clip.t()

Create a clip rectangle for a group.

close()

@spec close() :: String.t()

Close path command.

ellipse(cx, cy, rx, ry, rotation, start_angle, end_angle)

@spec ellipse(
  cx :: number(),
  cy :: number(),
  rx :: number(),
  ry :: number(),
  rotation :: number(),
  start_angle :: number(),
  end_angle :: number()
) :: list()

Ellipse path command.

image(source, x, y, w, h, opts \\ [])

@spec image(
  source :: String.t(),
  x :: number(),
  y :: number(),
  w :: number(),
  h :: number(),
  opts :: keyword()
) :: Plushie.Canvas.Shape.CanvasImage.t()

Draws a raster image on the canvas at the given position and size.

Options

  • :rotation -- rotation angle in radians.
  • :opacity -- opacity multiplier (0.0-1.0).

line(x1, y1, x2, y2, opts \\ [])

@spec line(
  x1 :: number(),
  y1 :: number(),
  x2 :: number(),
  y2 :: number(),
  opts :: keyword()
) :: Plushie.Canvas.Shape.Line.t()

Builds a line shape.

line_to(x, y)

@spec line_to(x :: number(), y :: number()) :: list()

Line-to path command.

linear_gradient(arg1, arg2, stops)

@spec linear_gradient(
  from :: {number(), number()},
  to :: {number(), number()},
  stops :: [{number(), String.t()}]
) :: Plushie.Canvas.Shape.LinearGradient.t()

Builds a linear gradient, usable as a fill value.

Stops are {offset, color} tuples where offset is 0.0..1.0.

move_to(x, y)

@spec move_to(x :: number(), y :: number()) :: list()

Move-to path command.

path(commands, opts \\ [])

@spec path(commands :: [map() | list() | String.t()], opts :: keyword()) ::
  Plushie.Canvas.Shape.Path.t()

Builds an arbitrary path shape.

Commands are produced by move_to/2, line_to/2, bezier_to/6, quadratic_to/4, arc/5, arc_to/5, ellipse/7, rounded_rect/5, and close/0.

quadratic_to(cpx, cpy, x, y)

@spec quadratic_to(cpx :: number(), cpy :: number(), x :: number(), y :: number()) ::
  list()

Quadratic bezier curve path command.

rect(x, y, w, h, opts \\ [])

@spec rect(
  x :: number(),
  y :: number(),
  w :: number(),
  h :: number(),
  opts :: keyword()
) ::
  Plushie.Canvas.Shape.Rect.t()

Builds a rectangle shape.

rotate(angle)

@spec rotate(angle_or_opts :: number() | keyword()) :: Plushie.Canvas.Shape.Rotate.t()

Create a rotation transform.

Accepts degrees by default. Use degrees: or radians: for explicit units.

rotate(45)              # 45 degrees
rotate(degrees: 45)     # explicit degrees
rotate(radians: 0.785)  # explicit radians

rounded_rect(x, y, w, h, radius)

@spec rounded_rect(
  x :: number(),
  y :: number(),
  w :: number(),
  h :: number(),
  radius :: number()
) :: list()

Rounded rectangle path command.

scale(factor)

@spec scale(factor :: number()) :: Plushie.Canvas.Shape.Scale.t()

Create a uniform scale transform.

scale(x, y)

@spec scale(x :: number(), y :: number()) :: Plushie.Canvas.Shape.Scale.t()

Create a non-uniform scale transform.

stroke(color, width, opts \\ [])

@spec stroke(color :: String.t(), width :: number(), opts :: keyword()) ::
  Plushie.Canvas.Shape.Stroke.t()

Builds a stroke descriptor.

Options

  • :cap -- line cap: "butt", "round", or "square". Default: "butt".
  • :join -- line join: "miter", "round", or "bevel". Default: "miter".
  • :dash -- dash pattern as {segments, offset} where segments is a list of numbers and offset is the starting offset.

svg(source, x, y, w, h)

@spec svg(
  source :: String.t(),
  x :: number(),
  y :: number(),
  w :: number(),
  h :: number()
) :: Plushie.Canvas.Shape.CanvasSvg.t()

Draws an SVG on the canvas at the given position and size.

text(x, y, content, opts \\ [])

@spec text(x :: number(), y :: number(), content :: String.t(), opts :: keyword()) ::
  Plushie.Canvas.Shape.CanvasText.t()

Builds a text shape.

translate(x, y)

@spec translate(x :: number(), y :: number()) :: Plushie.Canvas.Shape.Translate.t()

Create a translation transform.