freedive/lib/liliform/colorhash.ex

56 lines
1.3 KiB
Elixir

defmodule Liliform.Colorhash do
@moduledoc """
Given a string returns HSL color.
"""
alias Freedive.Features
require Logger
@seed "zeni"
@default_color {0, 0, 0}
@doc """
Given a string returns HSL color as a CSS string.
"""
def hsl(input) do
{hue, saturation, lightness} = hsl(input, raw: true)
"hsl(#{hue}, #{saturation}%, #{lightness}%)"
end
@doc """
Given a string returns HSL color.
"""
def hsl(input, raw: true) do
if Features.enabled?(:colorhash) do
input = String.downcase(input) <> @seed
hash = :erlang.phash2(input, 2_147_483_647)
hue = calculate_hue(hash)
saturation = 80 + rem(hash, 21)
lightness = 30 + rem(hash, 31)
{hue, saturation, lightness}
else
@default_color
end
end
@doc """
Calculates hue avoiding low contrast colors.
"""
def calculate_hue(hash) do
base_hue = rem(hash, 360)
# Ranges to exclude (yellow to light green, cyan)
excluded_ranges = [
# yellow
{40, 80},
# cyan
{175, 185}
]
# Adjust the hue to skip over excluded ranges
Enum.reduce(excluded_ranges, base_hue, fn {start, stop}, acc_hue ->
if acc_hue >= start and acc_hue <= stop, do: stop + (acc_hue - start + 1), else: acc_hue
end)
end
end