Method: Sass::Script::Functions#mix
- Defined in:
- lib/sass/script/functions.rb
#mix($color1, $color2, $weight: 50%) ⇒ Sass::Script::Value::Color
Mixes two colors together. Specifically, takes the average of each of the RGB components, optionally weighted by the given percentage. The opacity of the colors is also considered when weighting the components.
The weight specifies the amount of the first color that should be included
in the returned color. The default, 50%, means that half the first color
and half the second color should be used. 25% means that a quarter of
the first color and three quarters of the second color should be used.
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 |
# File 'lib/sass/script/functions.rb', line 1382
def mix(color1, color2, weight = number(50))
assert_type color1, :Color, :color1
assert_type color2, :Color, :color2
assert_type weight, :Number, :weight
Sass::Util.check_range("Weight", 0..100, weight, '%')
# This algorithm factors in both the user-provided weight (w) and the
# difference between the alpha values of the two colors (a) to decide how
# to perform the weighted average of the two RGB values.
#
# It works by first normalizing both parameters to be within [-1, 1],
# where 1 indicates "only use color1", -1 indicates "only use color2", and
# all values in between indicated a proportionately weighted average.
#
# Once we have the normalized variables w and a, we apply the formula
# (w + a)/(1 + w*a) to get the combined weight (in [-1, 1]) of color1.
# This formula has two especially nice properties:
#
# * When either w or a are -1 or 1, the combined weight is also that number
# (cases where w * a == -1 are undefined, and handled as a special case).
#
# * When a is 0, the combined weight is w, and vice versa.
#
# Finally, the weight of color1 is renormalized to be within [0, 1]
# and the weight of color2 is given by 1 minus the weight of color1.
p = (weight.value / 100.0).to_f
w = p * 2 - 1
a = color1.alpha - color2.alpha
w1 = ((w * a == -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0
w2 = 1 - w1
rgba = color1.rgb.zip(color2.rgb).map {|v1, v2| v1 * w1 + v2 * w2}
rgba << color1.alpha * p + color2.alpha * (1 - p)
rgb_color(*rgba)
end
|