@function cs-interpolate($value, $units: 360, $stops: #FF0000 #FF4900 #FF7400 #FF9200 #FFAA00 #FFBF00 #FFD300 #FFE800 #FFFF00 #CCF600 #9FEE00 #67E300 #00CC00 #00AF64 #009999 #0B61A4 #1240AB #1B1BB3 #3914AF #530FAD #7109AA #A600A6 #CD0074 #E40045) { // Loop numbers out of scale back into the scale. @while $value >= 360 { $value: $value - 360; } @while $value < 0 { $value: $value + 360; } // Find out how many units in each stop $cs-color-deg: $units / length($stops); // Count through stops $cs-deg-count: $cs-color-deg; $cs-stop-count: 1; // Add the first stop to the end so it will be // interpolated with the last stop. $stops: append($stops, nth($stops, 1)); // Start interpolating @for $i from 0 through length($stops) { @if $value < $cs-deg-count { @return mix(nth($stops, $cs-stop-count + 1), nth($stops, $cs-stop-count), abs(percentage(($cs-deg-count - $value) / $cs-color-deg) - 100 )); } // If the value is not in this stop, loop up to another stop. @else { $cs-deg-count: $cs-deg-count + $cs-color-deg; $cs-stop-count: $cs-stop-count + 1 } } } // RYB color interpolation @function find-ryb($hue) { // remove units on $hue @if unit($hue) == deg { $hue: $hue / 1deg; } // return an interpolated hue @return hue(cs-interpolate($hue)); } // Find the RYB hue instead of RGB hue of a color. // slow dumb loop at the moment. @function ryb-hue($color) { // find offset $hue: find-ryb(hue($color)) - hue($color); // apply the offset difference $hue: hue($color) - $hue; // Make within the range of 360 if not already. @while $hue >= 360deg { $hue: $hue - 360; } @while $hue < 0deg { $hue: $hue + 360; } @return $hue; } // Changes the hue of a color. @function ryb-adjust-hue($color, $degrees) { // Convert precentag to degrees. @if unit($degrees) == "%" { $degrees: 360 * ($degrees / 100%); } // Start at the current hue and loop in the adjustment. $hue-adjust: (ryb-hue($color) + $degrees) / 1deg; $saturation: saturation(cs-interpolate(abs(ryb-hue($color)) / 1deg)) - saturation($color); $lightness: lightness(cs-interpolate(abs(ryb-hue($color)) / 1deg)) - lightness($color); // Set hue of new color $new-color: cs-interpolate($hue-adjust); // Tint or shade according to lightness @if $lightness > 0 { $new-color: shade($new-color, $lightness * 2); } @if $lightness < 0 { $new-color: tint($new-color, abs($lightness)); } // Adjust saturation @if $saturation < 100% { $new-color: desaturate($new-color, abs($saturation)); } @return $new-color; } @function ryba($red, $yellow, $blue, $alpha) { $hue: 0; $saturation: 0; $lightness: percentage(($red + $yellow + $blue) / (255 * 3)); @if $red == $yellow and $yellow == $blue { @return hsla(0, 0, $lightness, $alpha); } @if $red >= $yellow and $red >= $blue { $hue: 0; } @elseif $yellow >= $red and $yellow >= $blue { $hue: 360 / 3; } @elseif $blue >= $red and $blue >= $yellow { $hue: 360 / 3 * 2; } @return hsla(hue(cs-interpolate($hue)), 100%, 50%, 1); } @function ryb($red, $yellow, $blue) { @return ryba($red, $yellow, $blue, 1); } @function set-ryb-hue($color, $hue) { @return hsla(hue(cs-interpolate($hue)), saturation($color), lightness($color), alpha($color)); } // Returns the complement of a color. @function ryb-complement($color) { @return ryb-adjust-hue($color, 180deg); } // Returns the inverse of a color. @function ryb-invert($color) { @return ryb-adjust-hue(hsl(hue($color), saturation(invert($color)), lightness(invert($color))), 180deg); }