defmodule Graditar do require Logger require ColorUtils require XmlBuilder alias ColorUtils.{ RGB } alias Graditar.{ Avatar } @moduledoc ~S""" Generate avatars made of an angled gradient ## Examples iex> Graditar.generate "\n\n\t\n\t\t\n\t\t\n\t\n\t\n" iex> Graditar.generate("bobthebuilder@canwefix.it") "\n\n\t\n\t\t\n\t\t\n\t\n\t\n" """ defp gen_hash(string) do hashlist = :crypto.hash(:md5, string) |> :binary.bin_to_list %Avatar{ hex: hashlist } end defp gen_primary_color(%Avatar{ hex: [r, g, b | _] } = avatar) 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) do [_, color] = ColorUtils.get_triad_colors primary_color %Avatar{ avatar | secondary_color: color } end defp gen_angle(%Avatar{ hex: [num | _] } = avatar) 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) 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})", 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: "100%", height: "100%", viewBox: "0 0 1 1", preserveAspectRatio: "none", }, [gradient, rect]) XmlBuilder.doc svg end def generate(string \\ "") do string |> gen_hash |> gen_primary_color |> gen_secondary_color |> gen_angle |> gen_svg end end