Class: Spectrum::Palette::MonoContrast

Inherits:
Object
  • Object
show all
Defined in:
lib/spectrum/palette/monocontrast.rb

Overview

Generates a monochromatic constrasting colour palette for background and foreground. What does this mean?

Monochromatic: A single colour is used to generate the base palette, and this colour is lightened five times and darkened five times to provide eleven distinct colours.

Contrasting: The foreground is also generated as a monochromatic colour palette; however, all generated colours are tested to see that they are appropriately contrasting to ensure maximum readability of the foreground against the background.

Constant Summary collapse

DEFAULT_MINIMUM_BRIGHTNESS_DIFF =
(125.0 / 255.0)
DEFAULT_MINIMUM_COLOR_DIFF =
(500.0 / 255.0)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(background, foreground = nil) ⇒ MonoContrast

Generate the initial palette.



88
89
90
91
92
93
# File 'lib/spectrum/palette/monocontrast.rb', line 88

def initialize(background, foreground = nil)
  @minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
  @minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF

  regenerate(background, foreground)
end

Instance Attribute Details

#backgroundObject (readonly)

Hash of CSS background colour values.

This is always 11 values:

0

The starting colour.

1..5

Lighter colours.

-1..-5

Darker colours.



34
35
36
# File 'lib/spectrum/palette/monocontrast.rb', line 34

def background
  @background
end

#foregroundObject (readonly)

Hash of CSS foreground colour values.

This is always 11 values:

0

The starting colour.

1..5

Lighter colours.

-1..-5

Darker colours.



42
43
44
# File 'lib/spectrum/palette/monocontrast.rb', line 42

def foreground
  @foreground
end

#minimum_brightness_diffObject

The minimum brightness difference between the background and the foreground, and must be between 0..1. Setting this value will regenerate the palette based on the base colours. The default value for this is 125 / 255.0. If this value is set to nil, it will be restored to the default.



51
52
53
# File 'lib/spectrum/palette/monocontrast.rb', line 51

def minimum_brightness_diff
  @minimum_brightness_diff
end

#minimum_color_diffObject

The minimum colour difference between the background and the foreground, and must be between 0..3. Setting this value will regenerate the palette based on the base colours. The default value for this is 500 / 255.0.



72
73
74
# File 'lib/spectrum/palette/monocontrast.rb', line 72

def minimum_color_diff
  @minimum_color_diff
end

Instance Method Details

#brightness_diff(c1, c2) ⇒ Object

Returns the absolute difference between the brightness levels of two colours. This will be a decimal value between 0 and 1. W3C accessibility guidelines for colour contrast suggest that this value be at least approximately 0.49 (125 / 255.0) for proper contrast.



166
167
168
# File 'lib/spectrum/palette/monocontrast.rb', line 166

def brightness_diff(c1, c2)
  (c1.brightness - c2.brightness).abs
end

#calculate_foreground(background, foreground) ⇒ Object

Given a background colour and a foreground colour, modifies the foreground colour so that it will have enough contrast to be seen against the background colour.

Uses #mininum_brightness_diff and #minimum_color_diff.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/spectrum/palette/monocontrast.rb', line 134

def calculate_foreground(background, foreground)
  nfg = nil
  # Loop through brighter and darker versions of the foreground color. The
  # numbers here represent the amount of foreground color to mix with
  # black and white.
  [100, 75, 50, 25, 0].each do |percent|
    dfg = foreground.darken_by(percent)
    lfg = foreground.lighten_by(percent)

    dbd = brightness_diff(background, dfg)
    lbd = brightness_diff(background, lfg)

    if lbd > dbd
      nfg = lfg
      nbd = lbd
    else
      nfg = dfg
      nbd = dbd
    end

    ncd = color_diff(background, nfg)

    break if nbd >= @minimum_brightness_diff and ncd >= @minimum_color_diff
  end
  nfg
end

#color_diff(c1, c2) ⇒ Object

Returns the contrast between to colours, a decimal value between 0 and

  1. W3C accessibility guidelines for colour

contrast suggest that this value be at least approximately 1.96 (500 / 255.0) for proper contrast.



174
175
176
177
178
179
# File 'lib/spectrum/palette/monocontrast.rb', line 174

def color_diff(c1, c2)
  r = (c1.r - c2.r).abs
  g = (c1.g - c2.g).abs
  b = (c1.b - c2.b).abs
  r + g + b
end

#regenerate(background, foreground = nil) ⇒ Object

Generate the colour palettes.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/spectrum/palette/monocontrast.rb', line 96

def regenerate(background, foreground = nil)
  foreground ||= background
  background = background.to_rgb
  foreground = foreground.to_rgb

  @background = {}
  @foreground = {}

  @background[-5] = background.darken_by(10)
  @background[-4] = background.darken_by(25)
  @background[-3] = background.darken_by(50)
  @background[-2] = background.darken_by(75)
  @background[-1] = background.darken_by(85)
  @background[ 0] = background
  @background[+1] = background.lighten_by(85)
  @background[+2] = background.lighten_by(75)
  @background[+3] = background.lighten_by(50)
  @background[+4] = background.lighten_by(25)
  @background[+5] = background.lighten_by(10)

  @foreground[-5] = calculate_foreground(@background[-5], foreground)
  @foreground[-4] = calculate_foreground(@background[-4], foreground)
  @foreground[-3] = calculate_foreground(@background[-3], foreground)
  @foreground[-2] = calculate_foreground(@background[-2], foreground)
  @foreground[-1] = calculate_foreground(@background[-1], foreground)
  @foreground[ 0] = calculate_foreground(@background[ 0], foreground)
  @foreground[+1] = calculate_foreground(@background[+1], foreground)
  @foreground[+2] = calculate_foreground(@background[+2], foreground)
  @foreground[+3] = calculate_foreground(@background[+3], foreground)
  @foreground[+4] = calculate_foreground(@background[+4], foreground)
  @foreground[+5] = calculate_foreground(@background[+5], foreground)
end