# `Color.Mix`

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.

# `gradient`

```elixir
@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`

```elixir
@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

* A `Color.SRGB` struct.

### 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"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
