class Passcard::Palette
Constants
- GOLDEN_RATIO
Attributes
colors[R]
options[R]
type[R]
Public Class Methods
new(type = :passcard, options = {})
click to toggle source
# File lib/passcard/palette.rb, line 9 def initialize(type = :passcard, options = {}) self.type = type self.options = options end
Public Instance Methods
list_types()
click to toggle source
# File lib/passcard/palette.rb, line 37 def list_types self.methods.map do |method| method.to_s.gsub!(/^generate_colors_/, '') end.compact.map(&:to_sym) end
options=(options = {})
click to toggle source
# File lib/passcard/palette.rb, line 24 def options=(options = {}) @options = options @options["n"] ||= (@options["size"][0] rescue 0) update_colors end
type=(type)
click to toggle source
# File lib/passcard/palette.rb, line 14 def type=(type) @type = type.to_s.strip.empty? ? :passcard : type.to_sym if !respond_to?("generate_colors_#{@type}", true) raise Passcard::Error, "No such color generator: #{@type}" end update_colors end
update_colors()
click to toggle source
# File lib/passcard/palette.rb, line 30 def update_colors return unless type && options @colors = send("generate_colors_#{type}", options).map do |rgb| { color: rgb, text_color: readable_text_color_for(rgb) } end end
Protected Instance Methods
generate_colors_gradient(options = {})
click to toggle source
# File lib/passcard/palette.rb, line 70 def generate_colors_gradient(options = {}) s = rand v = options.fetch("v", 0.93) from, to = generate_colors_martin_ankerl("s" => s, "v" => v, "n" => 2) options['n'].times.map do |i| m = i/options['n'].to_f 3.times.map{ |j| (from[j]*m + to[j] * (1-m)).round(0) } end end
generate_colors_krazydad(options = {})
click to toggle source
# File lib/passcard/palette.rb, line 56 def generate_colors_krazydad(options = {}) width = options.fetch('width', 55) center = options.fetch('center', 200) phase = options.fetch('phase', rand * Math::PI * 2.0) freq = Math::PI / options['n'] * 2.0 options['n'].times.map do |i| red = Math.sin(freq * i + 0 + phase) * width + center green = Math.sin(freq * i + 2 + phase) * width + center blue = Math.sin(freq * i + 4 + phase) * width + center [red.round(0), green.round(0), blue.round(0)] end end
generate_colors_martin_ankerl(options = {})
click to toggle source
# File lib/passcard/palette.rb, line 45 def generate_colors_martin_ankerl(options = {}) h = rand s = options.fetch('s', 0.33) v = options.fetch('v', 0.93) options['n'].times.map do h = (h + 1/GOLDEN_RATIO) % 1 hsv_to_rgb(h * 360, s, v) end end
generate_colors_passcard(options = {})
click to toggle source
# File lib/passcard/palette.rb, line 81 def generate_colors_passcard(options = {}) h = (360 * rand).round(2) n = options['n'] smax = options.fetch('smax', 0.4) n = n.times.map{|i| (1+i)/n.to_f * smax * 1.0} n.flatten.map{|s| hsl_to_rgb(h, s, 1 - s)} end
Private Instance Methods
hsl_to_rgb(h, s, l)
click to toggle source
# File lib/passcard/palette.rb, line 111 def hsl_to_rgb(h, s, l) c = (1 - (2 * l - 1).abs) * s x = c * (1 - ((h / 60.0) % 2 - 1).abs) m = l - c / 2.0 hue_to_rgb(h, c, x, m) end
hsv_to_rgb(h, s, v)
click to toggle source
# File lib/passcard/palette.rb, line 105 def hsv_to_rgb(h, s, v) c = v * s x = c * (1 - ((h / 60.0) % 2 - 1).abs) m = v - c hue_to_rgb(h, c, x, m) end
hue_to_rgb(h, c, x, m)
click to toggle source
For more info on conversions, read: en.wikipedia.org/wiki/HSL_and_HSV
Hue is specified in range: 0 <= hue < 360
# File lib/passcard/palette.rb, line 96 def hue_to_rgb(h, c, x, m) y = [c, 0, x] if h < 360 y = [x, 0, c] if h < 300 y = [0, x, c] if h < 240 y = [0, c, x] if h < 180 y = [x, c, 0] if h < 120 y = [c, x, 0] if h < 60 y.map{ |a| ((a + m) * 255).round(0) } end
luminosity_for(rgb)
click to toggle source
Read: www.w3.org/TR/WCAG20/#relativeluminancedef
# File lib/passcard/palette.rb, line 119 def luminosity_for(rgb) conv = rgb.map do |c| c/255.0 <= 0.03928 ? c/255.0/12.92 : ((c/255.0+0.055)/1.055)**2.4 end conv[0] * 0.2126 + conv[1] * 0.7152 + conv[2] * 0.0722 end
readable_text_color_for(rgb, dark = nil, light = nil)
click to toggle source
Read: www.w3.org/TR/WCAG20/#contrast-ratiodef
# File lib/passcard/palette.rb, line 127 def readable_text_color_for(rgb, dark = nil, light = nil) dark ||= [ 0, 0, 0] light ||= [255,255,255] lc, ld, ll = [rgb, dark, light].map{|color| luminosity_for(color)} (lc + 0.05) / (ld + 0.05) > (ll + 0.05) / (lc + 0.05) ? dark : light end