Преобразования систем цвета - не самая необходимая функция в PHP, хотя ... этот серверный язык часто работает на вывод HTML и CSS, а там задачи бывают разные. PHP не имеет встроенного универсального конвертера цветов, поэтому разработчики часто реализуют такие функции самостоятельно. Давайте разберемся, что мы можем сделать в этом направлении.
С точки зрения задач, преобразования систем цвета в PHP может использоваться в таких процессах:
- генерация тем;
- обработка изображений;
- сохранение цветов в БД в одном формате;
- динамическая стилизация писем / PDF / изображений.
С точки зрения управления цветом мы можем использовать такие цветовые функции из CSS, как HEX (например, #ff5733), RGB / RGBA? например яgb(255, 87, 51) или rgba(255, 87, 51, 0.8), а также HSL / HSV, например, hsl(207deg 100% 50%), которые удобны для:
- осветления / затемнения;
- изменения насыщенности;
- генерации палитр.
Давайте посмотрим, какие функции позволят нам выполнить различные преобразования.
Преобразование hex в rgb
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function get_rgb_values_from_hex( $hex ) { // Format the hex color string. $hex = str_replace( '#', '', $hex ); if ( 3 === strlen( $hex ) ) { $hex = str_repeat( substr( $hex, 0, 1 ), 2 ) . str_repeat( substr( $hex, 1, 1 ), 2 ) . str_repeat( substr( $hex, 2, 1 ), 2 ); } // Get decimal values. $r = hexdec( substr( $hex, 0, 2 ) ); $g = hexdec( substr( $hex, 2, 2 ) ); $b = hexdec( substr( $hex, 4, 2 ) ); return array( 'r' => $r, 'g' => $g, 'b' => $b, ); } |
На основе предыдущей функции мы можем получить более светлый цвет:
|
1 2 3 4 5 |
function is_color_light( $hex ) { $rgb_values = get_rgb_values_from_hex( $hex ); $average_lightness = ( $rgb_values['r'] + $rgb_values['g'] + $rgb_values['b'] ) / 3; return $average_lightness >= 127.5; } |
Преобразование rgb в hex
И еще понадобится функция преобразования RGB в HEX:
|
1 2 3 4 |
function rgbToHex(int $r, int $g, int $b): string { return sprintf('#%02X%02X%02X', $r, $g, $b); } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/** Adjust a hex color brightness Allows us to create hover styles for custom link colors @since 2.5.8 Added $opacity argument. @param $hex color e.g. #111111. @param integer $steps - Factor by which to brighten/darken ranging from -255 (darken) to 255 (brighten). @param $opacity - Opacity factor between 0 and 1. @return string Brightened/darkened color (hex by default, rgba if opacity is set to a valid value below 1). */ function storefront_adjust_color_brightness( $hex, $steps, $opacity = 1 ) { // Steps should be between -255 and 255. Negative = darker, positive = lighter. $steps = max( -255, min( 255, $steps ) ); $rgb_values = get_rgb_values_from_hex( $hex ); // Adjust number of steps and keep it inside 0 to 255. $r = max( 0, min( 255, $rgb_values['r'] + $steps ) ); $g = max( 0, min( 255, $rgb_values['g'] + $steps ) ); $b = max( 0, min( 255, $rgb_values['b'] + $steps ) ); if ( $opacity >= 0 && $opacity < 1 ) { return 'rgba(' . $r . ',' . $g . ',' . $b . ',' . $opacity . ')'; } $r_hex = str_pad( dechex( $r ), 2, '0', STR_PAD_LEFT ); $g_hex = str_pad( dechex( $g ), 2, '0', STR_PAD_LEFT ); $b_hex = str_pad( dechex( $b ), 2, '0', STR_PAD_LEFT ); return '#' . $r_hex . $g_hex . $b_hex; } |
Преобразование RGB в HSL
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function rgbToHsl(int $r, int $g, int $b): array { $r /= 255; $g /= 255; $b /= 255; $max = max($r, $g, $b); $min = min($r, $g, $b); $l = ($max + $min) / 2; if ($max === $min) { return ['h' => 0, 's' => 0, 'l' => round($l * 100)]; } $d = $max - $min; $s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min); switch ($max) { case $r: $h = (($g - $b) / $d + ($g < $b ? 6 : 0)) * 60; break; case $g: $h = (($b - $r) / $d + 2) * 60; break; default: $h = (($r - $g) / $d + 4) * 60; } return [ 'h' => round($h), 's' => round($s * 100), 'l' => round($l * 100), ]; } |
Преобразование HSL в RGB
Новая функция:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function hslToRgb(float $h, float $s, float $l): array { if ($s == 0) { $v = (int)round($l * 255); return [$v, $v, $v]; } $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s; $p = 2 * $l - $q; $hk = $h / 360; $t = [$hk + 1/3, $hk, $hk - 1/3]; foreach ($t as &$tc) { if ($tc < 0) $tc += 1; if ($tc > 1) $tc -= 1; if ($tc < 1/6) { $tc = $p + ($q - $p) * 6 * $tc; } elseif ($tc < 1/2) { $tc = $q; } elseif ($tc < 2/3) { $tc = $p + ($q - $p) * (2/3 - $tc) * 6; } else { $tc = $p; } } return [ (int)round($t[0] * 255), (int)round($t[1] * 255), (int)round($t[2] * 255), ]; } |
Код для генерации цветов темы
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
<?php // ---------- HEX → RGB ---------- function hexToRgb(string $hex): array { $hex = ltrim($hex, '#'); if (strlen($hex) === 3) { $hex = preg_replace('/(.)/', '$1$1', $hex); } return [ hexdec(substr($hex, 0, 2)), hexdec(substr($hex, 2, 2)), hexdec(substr($hex, 4, 2)), ]; } // ---------- RGB → HEX ---------- function rgbToHex(int $r, int $g, int $b): string { return sprintf('#%02X%02X%02X', $r, $g, $b); } // ---------- RGB → HSL ---------- function rgbToHsl(int $r, int $g, int $b): array { $r /= 255; $g /= 255; $b /= 255; $max = max($r, $g, $b); $min = min($r, $g, $b); $l = ($max + $min) / 2; if ($max === $min) { return [0, 0, $l]; } $d = $max - $min; $s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min); switch ($max) { case $r: $h = (($g - $b) / $d + ($g < $b ? 6 : 0)) * 60; break; case $g: $h = (($b - $r) / $d + 2) * 60; break; default: $h = (($r - $g) / $d + 4) * 60; } return [$h, $s, $l]; } // ---------- HSL → RGB ---------- function hslToRgb(float $h, float $s, float $l): array { if ($s == 0) { $v = (int)round($l * 255); return [$v, $v, $v]; } $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s; $p = 2 * $l - $q; $hk = $h / 360; $t = [$hk + 1/3, $hk, $hk - 1/3]; foreach ($t as &$tc) { if ($tc < 0) $tc += 1; if ($tc > 1) $tc -= 1; if ($tc < 1/6) { $tc = $p + ($q - $p) * 6 * $tc; } elseif ($tc < 1/2) { $tc = $q; } elseif ($tc < 2/3) { $tc = $p + ($q - $p) * (2/3 - $tc) * 6; } else { $tc = $p; } } return [ (int)round($t[0] * 255), (int)round($t[1] * 255), (int)round($t[2] * 255), ]; } // ---------- Генерация палитры ---------- $baseColor = $_GET['color'] ?? '#4f46e5'; [$r, $g, $b] = hexToRgb($baseColor); [$h, $s, $l] = rgbToHsl($r, $g, $b); $background = rgbToHex(...hslToRgb($h, $s, min($l + 0.25, 1))); $accent = rgbToHex(...hslToRgb($h, $s, max($l - 0.25, 0))); ?> <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>PHP Color Palette</title> <style> body { font-family: sans-serif; background: <?= $background ?>; color: <?= $baseColor ?>; padding: 40px; } .card { background: #fff; padding: 20px; border-left: 8px solid <?= $accent ?>; } input { padding: 6px; } </style> </head> <body> <form> <label> Выберите цвет: <input type="color" name="color" value="<?= $baseColor ?>"> </label> <button>Применить</button> </form> <div class="card"> <h2>Динамическая тема</h2> <p><strong>Основной цвет:</strong> <?= $baseColor ?></p> <p><strong>Фон:</strong> <?= $background ?></p> <p><strong>Акцент:</strong> <?= $accent ?></p> </div> </body> </html> |
Еще одна практическая задача - сгенерировать оттенки цвета:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
function hex2rgb($hex) { return array( hexdec(substr($hex,1,2)), hexdec(substr($hex,3,2)), hexdec(substr($hex,5,2)) ); } function different_shade($rgb, $type) { $newShade = array(); $percentageChange = 7.5; if($type == 'lighter') { $newShade = Array( 255-(255-$rgb[0]) + $percentageChange, 255-(255-$rgb[1]) + $percentageChange, 255-(255-$rgb[2]) + $percentageChange ); } else { $newShade = Array( $rgb[0] - $percentageChange, $rgb[1] - $percentageChange, $rgb[2] - $percentageChange ); } return $newShade; } |