Packages

A set of helper modules to generate gradient-based avatars.

Current section

Files

Jump to
graditar lib graditar.ex
Raw

lib/graditar.ex

defmodule Graditar do
require ColorUtils
require XmlBuilder
alias ColorUtils.{ RGB }
alias Graditar.{ Avatar, Options }
@moduledoc ~S"""
Generate avatars made of an angled gradient
## Examples
Generate a generic svg
iex> Graditar.generate
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<svg height=\"512px\" preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\" width=\"512px\" xmlns=\"http://www.w3.org/2000/svg\">\n\t<linearGradient gradientTransform=\"rotate(315 .5 .5)\" gradientUnits=\"userSpaceOnUse\" id=\"gradient\" x1=\"0%\" x2=\"0%\" y1=\"0%\" y2=\"100%\">\n\t\t<stop offset=\"0%\" stop-color=\"rgb(212, 29, 140)\" stop-opacity=\"1\"/>\n\t\t<stop offset=\"100%\" stop-color=\"rgb(120, 211, 28)\" stop-opacity=\"1\"/>\n\t</linearGradient>\n\t<rect fill=\"url(#gradient)\" height=\"1\" width=\"1\" x=\"0\" y=\"0\"/>\n</svg>"
Generate from a string
iex> Graditar.generate("bobthebuilder@canwefix.it")
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<svg height=\"512px\" preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\" width=\"512px\" xmlns=\"http://www.w3.org/2000/svg\">\n\t<linearGradient gradientTransform=\"rotate(225 .5 .5)\" gradientUnits=\"userSpaceOnUse\" id=\"gradient\" x1=\"0%\" x2=\"0%\" y1=\"0%\" y2=\"100%\">\n\t\t<stop offset=\"0%\" stop-color=\"rgb(145, 79, 1)\" stop-opacity=\"1\"/>\n\t\t<stop offset=\"100%\" stop-color=\"rgb(73, 145, 1)\" stop-opacity=\"1\"/>\n\t</linearGradient>\n\t<rect fill=\"url(#gradient)\" height=\"1\" width=\"1\" x=\"0\" y=\"0\"/>\n</svg>"
Add options
iex> Graditar.generate("bobthebuilder@canwefix.it", %{ size: 128 })
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<svg height=\"128px\" preserveAspectRatio=\"none\" viewBox=\"0 0 1 1\" width=\"128px\" xmlns=\"http://www.w3.org/2000/svg\">\n\t<linearGradient gradientTransform=\"rotate(225 .5 .5)\" gradientUnits=\"userSpaceOnUse\" id=\"gradient\" x1=\"0%\" x2=\"0%\" y1=\"0%\" y2=\"100%\">\n\t\t<stop offset=\"0%\" stop-color=\"rgb(145, 79, 1)\" stop-opacity=\"1\"/>\n\t\t<stop offset=\"100%\" stop-color=\"rgb(73, 145, 1)\" stop-opacity=\"1\"/>\n\t</linearGradient>\n\t<rect fill=\"url(#gradient)\" height=\"1\" width=\"1\" x=\"0\" y=\"0\"/>\n</svg>"
"""
defp gen_hash(string, _opts) do
hashlist = :crypto.hash(:md5, string)
|> :binary.bin_to_list
%Avatar{ hex: hashlist }
end
defp gen_primary_color(%Avatar{ hex: [r, g, b | _] } = avatar, _opts) do
color = %RGB{ red: r, green: g, blue: b }
%Avatar{ avatar | primary_color: color }
end
defp gen_secondary_color(%Avatar{ primary_color: primary_color } = avatar, _opts) do
[_, color] = ColorUtils.get_triad_colors primary_color
%Avatar{ avatar | secondary_color: color }
end
defp gen_angle(%Avatar{ hex: [num | _] } = avatar, _opts) do
# Generate an angle, one of 45, 135, 225, or 315
angle = (round(Float.floor(num / 64)) + 1) * 45 * 2 - 45
%Avatar{ avatar | angle: angle }
end
defp gen_svg(avatar, %{ size: size } = _opts) do
%Avatar{ primary_color: primary_color, secondary_color: secondary_color, angle: angle } = avatar
%RGB{ red: p_r, blue: p_b, green: p_g } = primary_color
%RGB{ red: s_r, blue: s_b, green: s_g } = secondary_color
primary_color_stop = XmlBuilder.element(:stop, %{
offset: "0%",
"stop-color": "rgb(#{p_r}, #{p_g}, #{p_b})",
"stop-opacity": "1",
})
secondary_color_stop = XmlBuilder.element(:stop, %{
offset: "100%",
"stop-color": "rgb(#{s_r}, #{s_g}, #{s_b})",
"stop-opacity": "1",
})
gradient = XmlBuilder.element(:linearGradient, %{
id: "gradient",
gradientUnits: "userSpaceOnUse",
gradientTransform: "rotate(#{angle} .5 .5)",
x1: "0%",
x2: "0%",
y1: "0%",
y2: "100%",
}, [primary_color_stop, secondary_color_stop])
rect = XmlBuilder.element(:rect, %{
x: 0,
y: 0,
width: 1,
height: 1,
fill: "url(#gradient)",
})
svg = XmlBuilder.element(:svg, %{
xmlns: "http://www.w3.org/2000/svg",
width: "#{size}px",
height: "#{size}px",
viewBox: "0 0 1 1",
preserveAspectRatio: "none",
}, [gradient, rect])
XmlBuilder.doc svg
end
def generate(string \\ "", opts \\ %Options{}) do
string
|> gen_hash(opts)
|> gen_primary_color(opts)
|> gen_secondary_color(opts)
|> gen_angle(opts)
|> gen_svg(opts)
end
end