Main features
-
support for CSS Color Module Level 3 color specifications
- #a02917
- rgb(160, 41, 23)
- hsl(8, 75%, 36%)
-
support for alpha transparency
- #a0291780
- rgb(160, 41, 23, 0.5)
- hsl(8, 75%, 36%, 0.5)
- modifiers to change red/green/blue or hue/saturation/lightness and alpha on any color type
- support for custom colorspaces which can then be converted to other colorspaces
- support for custom modifiers which can be applied to any colorspace
- immutable behaviour
- support for CSS color keywords
Conversion
hsl(208, 40%, 41%)echo (string) Color::fromString('#3f6c93')->toHsl();
Modification and immutability
The Color object is immutable - so conversions and modifications will return a new Color object.
We can set the red channel (or green or blue) to any integer value from 0 to 255.
#333333$color = Color::fromString('#333333');
#643333$color->red(100);
We can add or subtract an absolute value to or from the red channel (or green or blue). However, these channels are limited to values between 0 and 255 inclusive.
#333333$color = Color::fromString('#333333');
#973333$color->red('+100');
#332933$color->green('-10');
#3333ff$color->blue('+300');
#003333$color->red('-100');
Alternatively, we can use relative values to modify any of the color channels:
#333333$color = Color::fromString('#333333');
#333366$color->blue('+100%');
#331a33$color->green('-50%');
Finally, you can set the channel to a value between it's current value and the upper (or lower) limit by passing a fractional argument.
#333399$color->blue('+1/2');
#333326$color->blue('+1/2');
Any modifier can be applied to any colorspace.
For example, you can modify the hue, saturation or lightness of a HEX or RGB color, or you can modify a HSL by changing it's red, green or blue values.
#993333$color = Color::fromString('#993333');
#339933$color->hue('+120');
#339933$color->hue('+480');
#333399$color->hue('-120');
#a62626$color->saturation('+25%');
#732626$color->lightness('-25%');
hsl(0, 50%, 50%)$color = Color::fromString('hsl(0, 50%, 50%)');
hsl(293, 55.3%, 51.7%)$color->blue('200');
Note that saturation and lightness are limited to any value between 0 and 100%, while hue is cyclic and unlimited (though you should try to remain in the bounds of 0–360°). This means a hue of 390° is the equivalent of 30° and also −330°.
The open-ended value of hue also means that relative and fractional modifications are not possible.
Custom color types
Custom color types must extend the Color
abstract class, and also implement the following methods
from ColorInterface
:
public static function fromString(string $colorSpec): ColorInterface;
public function __toString(): string;
public static function fromRgb(Rgb $rgb): ColorInterface;
public function toRgb(): Rgb;
class Gray extends Color implements ColorInterface
{
protected $value;
/**
* @param float $value A percentage value, 0 for black and 100 for white.
* @param float $alpha The alpha channel, 0.0 for complete transparency and 1.0 for complete opacity.
*/
public function __construct(float $value, float $alpha = 1.0)
{
$this->value = min(max($value, 0), 100); // limit value to be between 0 and 100
$this->alpha = min(max($alpha, 0), 1.0); // limit alpha to be between 0 and 1.0
}
/**
* Create a new Gray color from the provided color specification.
*
* @param string $colorSpec Accepted formats: gray(50%) or gray(50%, 0.5)
*/
public static function fromString(string $colorSpec): ColorInterface
{
}
/**
* Output a string representation of the Gray color - gray(50%) or gray(50%, 0.5) (with an alpha channel)
*
* @return string Either of the following formats, depending on whether an alpha channel has been set: gray(50%) or gray(50%, 0.5)
*/
public function __toString(): string
{
}
/**
* Create a new instance of Gray based on the provided Rgb
*
* @param Rgb $rgb
* @return Gray Return a new instance of Gray based on the RGB values in the provided object.
*/
public static function fromRgb(Rgb $rgb): ColorInterface
{
}
/**
* Create a new instance of an Rgb color based on the Gray value.
* @param Rgb $rgb
*/
public function toRgb(): Rgb
{
}
}
Creation - fromString
public static function fromString(string $colorSpec): ColorInterface
{
$channels = Color::extractChannels($colorSpec, self::class);
// $channels[1] is the gray value
// $channels[3] is the optional alpha channel
if (!isset($channels[3])) {
$channels[3] = 1.0;
}
return new Gray((float) $channels[1], (float) $channels[3]);
}
To be able to create a Gray color from a string specification, you must first register the color object and one or more regex patterns for the color specification.
Color::registerColor('Gray', Gray::class);
Color::registerColorSpec('gray\((\d{1,3}(\.\d{1,2})?)%\)', Gray::class); // gray(50%)
Color::registerColorSpec('gray\((\d{1,3}(\.\d{1,2})?)%,\s*([0-1](\.\d{1,2})?)\)', Gray::class); // gray(50%, 0.5)
$gray = Color::fromString("gray(50%, 0.5)");
Conversion - fromRgb
and toRgb
To convert between color types, you only need to implement conversions from and to RGB types. You will then be able to convert between any other registered type.
public static function fromRgb(Rgb $rgb): ColorInterface
{
$average = ($rgb->red + $rgb->green + $rgb->blue) / 3;
$gray = $average * 100 / 255; // rgb values are in the range 0-255, gray values are 0-100%
return new Gray($gray, $rgb->alpha); // copies the original alpha value
}
public function toRgb(): Rgb
{
$gray = $this->value * 255 / 100; // scale the gray value to 0-255 for ease
$return new Rgb($gray, $gray, $gray, $this->alpha); // all color channels are equal, and copy the current alpha value
}
Color::registerColor('Gray', Gray::class);
$hex = Color::fromString('#339966');
$gray = $hex->toGray();
echo (string) $gray; // gray(40%);
$hex = Color::fromString('#33996680');
$gray = $hex->toGray();
echo (string) $gray; // gray(40%, 0.5);
Custom color modifiers
Calling a modifier on any color type will convert it to the type that implements the registered method, and then convert the result back to the original type.
For example, the saturation modifier is defined on the Hsl colorspace class. If we wish to increase the saturation of an Rgb color, the library will convert from that value to an intermediary Hsl color, apply the change to the saturation, and then return a new Rgb with the changes applied.
To allow this implicit conversion, custom modifier methods must return an object which extends the
abstract Color
class.
Ideally, it should return a copy of the same type the method is implemented on.
/**
* Change the gray value of a color
*
* @param $gray The change to the grayness of this color.
* @return self This will return a copy of the Gray class.
*/
public function gray($gray): self
{
$gray = $this->adjustValue($this->gray, $gray, 100);
$gray = min($gray, max($gray, 0)); // gray is limited to 0 to 100
return new self($gray, $this->alpha); // return a copy of the Gray object
}
adjustValue
is a method on the abstract Color
class that handles the different values allowed for adjustment (including relative or fractional changes)
and returns the new absolute value for that property.
Support for color keywords
You can create a Hex color using any of the CSS color keywords:
#483d8b$hex = Color::fromString('darkslateblue');
hsl(248, 39%, 39%)$hsl = Color::fromString('darkslateblue')->toHsl;
Built-in modifiers
All of the built-in modifiers can be applied to any color type that implements the ColorInterface
.
alpha
- set or adjust the transparency of the color (limited between 0 and 100%).red
- set or adjust the redness of the color (limited between 0 and 255).green
- set or adjust the greenness of the color (limited between 0 and 255).blue
- set or adjust the blueness of the color (limited between 0 and 255).hue
- set or adjust the hue of the color.saturation
- set or adjust the saturation of the color (limited between 0 and 100%).lightness
- set or adjust the lightness of the color (limited between 0 and 100%).invert
- inverts the color by adding 180° to the hue.