Colors are a vital part of web design. You can see that in a lot of website designs, even in particular cases like woodworking websites, for example. They can easily make or break a design. Oftentimes, designers are interested in modifying colors by mixing, fading, or brightening them. This will be the basis for today’s article.
We’re going to go through the process of creating a simple color manager with object-oriented PHP. Rather than focusing on multiple forms of modification, our color manager will perform one basic function: fading. Given a base color (hexadecimal) and a fade percentage, we will calculate a new, faded color.
Fading, when taken from a red-green-blue (RGB) color perspective, only involves linear interpolation. In other words, to fade a color from blue rgb( 0, 0, 255 )
to white rgb( 255, 255, 255 )
, each color component must be increased by a percentage of the difference to the target component.
To elucidate this statement, consider the following example: if you wanted to fade 10% from blue to white, you would calculate the components as such:
original color (blue) = rgb( 0, 0, 255 )
target color (white) = rgb( 255, 255, 255 )
fade percent = 10%
original color's red component = 0
target color's red component = 255
difference in components = 255 - 0
= 255
new red component = original red component + difference in components * fade percent
new red component = 0 + 255 * .10
= 25.5
This process would be repeated with the two other components. The new color (after all calculations) would be:
rgb( 25.5, 25.5, 255 );
If you were to look at this color, it would be a faded blue.
Since we are working with a hexadecimal color, it would be beneficial to convert it to RGB, fade it, and then convert back. Although there are ways to fade directly in hexadecimal format, this path begs the use of object-oriented PHP and does not require a knowledge of bit manipulation.
Hexadecimal
Before starting to code, you must first understand how to convert from hexadecimal to RGB and back. The first two letters/digits in a hex color represent the red component in an RGB color. In like manner, the third and fourth letters/digits represent the green component. Finally, the last two digits represent the blue component. After splitting the hex color into these three sets, each one must be converted from base 16 to base 10 to get the final RGB color:
hex color (white) = FFFFFF
red component = FF (base 16)
= 255 (base 10)
green component = FF (base 16)
= 255 (base 10)
blue component = FF (base 16)
= 255 (base 10)
hex color (white) = rgb( 255, 255, 255 )
To go from RGB to hexadecimal, convert each component to base 16 and concatenate them:
rgb color (white) = ( 255, 255, 255 )
red component = 255 (base 10)
= FF (base 16)
green component = 255 (base 10)
= FF (base 16)
blue component = 255 (base 10)
= FF (base 16)
rgb color (white) = hex FFFFFF
Now we can move on to the implementation. To begin, we will first write a HexColor
class, which will hold a $hex
variable representing the hex string. This class will provide a function to convert to an RGB color:
class HexColor {
private $hex;
public function HexColor( $hex )
{
if( strpos( $hex, '#' ) === 0 )
$this->hex = substr( $hex, 1 );
else
$this->hex = $hex;
}
public function getHexString()
{
return $this->hex;
}
public function convertToRGB()
{
// first two digits represent red, next two blue, and the last two green
$red = substr( $this->hex, 0, 2 );
$green = substr( $this->hex, 2, 2 );
$blue = substr( $this->hex, 4, 2 );
// convert from hexadecimal to base 10
$red = (int) base_convert( $red, 16, 10 );
$green = (int) base_convert( $green, 16, 10 );
$blue = (int) base_convert( $blue, 16, 10 );
return new RGBColor( $red, $green, $blue );
}
public static function isValid( $hex )
{
return (bool) preg_match( '/^(#)?[a-zA-Z0-9]{6}$/', $hex );
}
public function __toString()
{
return $this->hex;
}
}
Note that the isValid
function is used to check whether a given string is a valid hex color.
RGB
Next is the RGBColor
class, which contains similar functionality and a fadeTo
function based off of the calculations explained at the beginning of this article:
class RGBColor {
private $red, $green, $blue;
public function RGBColor( $red, $green, $blue )
{
$this->red = $this->clamp( $red );
$this->green = $this->clamp( $green );
$this->blue = $this->clamp( $blue );
}
public function getRed()
{
return $this->red;
}
public function getGreen()
{
return $this->green;
}
public function getBlue()
{
return $this->blue;
}
public function fadeTo( $rgbColor, $percent )
{
$newRed = ( 1 - $percent ) * $this->red + $percent * $rgbColor->getRed();
$newGreen = ( 1 - $percent ) * $this->green + $percent * $rgbColor->getGreen();
$newBlue = ( 1 - $percent ) * $this->blue + $percent * $rgbColor->getBlue();
return new RGBColor( (int) $newRed, (int) $newGreen, (int) $newBlue );
}
public function convertToHex()
{
$newRed = base_convert( $this->red, 10, 16 );
$newGreen = base_convert( $this->green, 10, 16 );
$newBlue = base_convert( $this->blue, 10, 16 );
$newRed = $this->addZero( $newRed );
$newGreen = $this->addZero( $newGreen );
$newBlue = $this->addZero( $newBlue );
return new HexColor( $newRed . $newGreen . $newBlue );
}
private function addZero( $colorValue )
{
if( strlen( $colorValue ) == 1 )
$colorValue = '0' . $colorValue;
return $colorValue;
}
private function clamp( $colorValue )
{
// clamp colorValue in interval [0, 255]
return max( 0, min( 255, $colorValue ) );
}
public function __toString()
{
return '(' . $this->red . ', ' . $this->green . ', ' . $this->blue . ')';
}
}
Since RGB color values can only be in the 0-255 range, the clamp
function is used to ensure this is true. In addition, the addZero
function makes sure the hex color is six digits long by prepending the necessary 0s.
Given these classes, a $hex
string, and a $fade
percentage, the process to fade a hex color is as follows:
- Instantiate a
HexColor
object with the$hex
string - Convert it to an
RGBColor
- Call the
fadeTo
function with the given$fade
percentage and the color white - Convert the
RGBColor
back to aHexColor
and display it
In addition, to make this more flexible, we can change the third step to darken the color (fade to black) if the fade percentage is negative. These instructions lead to the following code:
$hexColor = new HexColor( $hex );
// target color is white by default
$targetColor = new RGBColor( 255, 255, 255 );
// want to darken the color--target is black
if( $fade < 0 ) {
$targetColor = new RGBColor( 0, 0, 0 );
$fade = -$fade; // make fade positive
}
$rgbColor = $hexColor->convertToRGB();
// fade / 100 is the percentage
$fadedColor = $rgbColor->fadeTo( $targetColor, $fade / 100 );
echo $fadedColor->convertToHex();
Combined with some AJAX, form handling, and CSS (which I won’t be going over, as this was a lesson in object-oriented PHP), this code ultimately results in a simple color manager, which you may view/download using the buttons below.