Search⌘ K
AI Features

Compos With Componentsing

Explore building interactive SVG graphics by creating reusable components such as Shape, Palette, and Canvas with Phoenix LiveView. Learn to organize points into shapes, build dynamic palettes, and render complex visuals for real-time web games.

We’ll use the <Point> and <Canvas> components to render more complex graphics. We’ll roll up a collection of points with common colors and names into shapes represented by a <Shape> component. Then, we’ll assemble shapes to display the palette of pentominoes for a game. We’ll also use a single rectangular shape of a given size to represent the game’s puzzle board. When we’re done, the design of our components will look something like this:

The <Board> component contains a <Canvas> that renders a single <Shape> depicting our puzzle board. It also renders the <Palette> containing a <Canvas> to display the set of <Shape> components representing the game’s pentominoes. Let’s start building out this structure now.

Rendering shapes with multiple points

First up, we start by building a <Shape> component that knows how to render the list of points that make up a given shape. To do so, we create a new file, pento/lib/pento_web/live/pento/shape.ex and define our stateless component like this:

Elixir
defmodule PentoWeb.Pento.Shape do
use Surface.Component
alias PentoWeb.Pento.Point

Then, we declare the points, fill, and name props in pento/lib/pento_web/live/pento/shape.ex, that our <Shape> needs:

Elixir
prop points, :list
prop fill, :string
prop name, :string

Each shape will have a :list of points, a shape name of type :string, and a fill of type :string representing the color. Like the core Shape module, a <Shape> component has a name, color, and collection of points. The fill property is a little different than the color attribute in the core Shape struct though. We’ll translate the color field from the core struct into HTML-friendly hex codes in the PentoWeb.Pento.Colors helper module. To do so, we create pento/lib/pento_web/live/pento/colors.ex and add the following code like this:

Elixir
defmodule PentoWeb.Pento.Colors do
def color(c), do: color(c, false)
def color(_color, true), do: "#B86EF0"
def color(:green, _active), do: "#8BBF57"
def color(:dark_green, _active), do: "#689042"
def color(:light_green, _active), do: "#C1D6AC"
def color(:orange, _active), do: "#B97328"
def color(:dark_orange, _active), do: "#8D571E"
def color(:light_orange, _active), do: "#F4CCA1"
def color(:gray, _active), do: "#848386"
def color(:dark_gray, _active), do: "#5A595A"
def color(:light_gray, _active), do: "#B1B1B1"
def color(:blue, _active), do: "#83C7CE"
def color(:dark_blue, _active), do: "#63969B"
def color(:light_blue, _active), do: "#B9D7DA"
def color(:purple, _active), do: "#240054"
end

The pentominoes all have their own color mappings. In addition, a user will place one pentomino on the board at a time, and later we’ll apply a highlighted color to this active shape.

The Colors module ...