Color.Mix (Color v0.4.0)

Copy Markdown

Color interpolation and gradient generation.

  • mix/3,4 — linearly interpolate between two colors in a named working space. The space matters a lot: mixing red and green in sRGB gives muddy brown at t = 0.5, while mixing in Oklab gives a clean olive. Default is Color.Oklab, matching CSS Color 4's color-mix() recommendation.

  • gradient/4 — return a list of n evenly spaced colors from start to stop, inclusive of both endpoints.

Both functions accept anything Color.new/1 accepts and always return the mixed color as a Color.SRGB struct (so it's ready to display). If you need the result in a different space, pipe it through Color.convert/2 afterwards.

Hue interpolation is handled specially for cylindrical spaces (Color.LCHab, Color.LCHuv, Color.Oklch, Color.HSLuv, Color.HPLuv, Color.HSL, Color.HSV): by default we take the shorter arc around the hue circle. Pass hue: :longer, hue: :increasing or hue: :decreasing to force a different path, matching the CSS Color 4 hue-interpolation modes.

Summary

Functions

Generates an evenly-spaced gradient between start and stop.

Mixes two colors in the given working space.

Functions

gradient(start, stop, steps, options \\ [])

@spec gradient(Color.input(), Color.input(), pos_integer(), keyword()) ::
  {:ok, [Color.SRGB.t()]} | {:error, Exception.t()}

Generates an evenly-spaced gradient between start and stop.

Arguments

  • start is any color accepted by Color.new/1.

  • stop is any color accepted by Color.new/1.

  • steps is the number of colors to return, ≥ 2. The first result is start and the last result is stop.

  • options is the same as for mix/4.

Returns

  • {:ok, [%Color.SRGB{}, ...]} with steps elements.

Examples

iex> {:ok, colors} = Color.Mix.gradient("black", "white", 3)
iex> Enum.map(colors, &Color.SRGB.to_hex/1)
["#000000", "#636363", "#ffffff"]

iex> {:ok, colors} = Color.Mix.gradient("red", "blue", 5)
iex> length(colors)
5

mix(a, b, t, options \\ [])

@spec mix(Color.input(), Color.input(), number(), keyword()) ::
  {:ok, Color.SRGB.t()} | {:error, Exception.t()}

Mixes two colors in the given working space.

Arguments

  • a is any color accepted by Color.new/1.

  • b is any color accepted by Color.new/1.

  • t is the mixing parameter in [0, 1]. 0.0 returns a, 1.0 returns b, 0.5 returns the midpoint.

  • options is a keyword list.

Options

  • :in is the color space module to interpolate in. Defaults to Color.Oklab.

  • :hue is the hue-interpolation mode for cylindrical spaces: :shorter (default), :longer, :increasing, :decreasing.

Returns

Examples

iex> {:ok, mid} = Color.Mix.mix("red", "lime", 0.5)
iex> hex = Color.SRGB.to_hex(mid) |> String.upcase()
iex> String.starts_with?(hex, "#")
true

iex> {:ok, mid} = Color.Mix.mix("red", "lime", 0.5, in: Color.SRGB)
iex> Color.SRGB.to_hex(mid) |> String.upcase()
"#7F8000"

iex> {:ok, a} = Color.Mix.mix("red", "blue", 0.0)
iex> {:ok, b} = Color.Mix.mix("red", "blue", 1.0)
iex> {Color.SRGB.to_hex(a), Color.SRGB.to_hex(b)}
{"#ff0000", "#0000ff"}