У меня есть шестнадцатеричное значение некоторого цвета, например #202010
.
Как сгенерировать новый цвет, который светлее или темнее задан в процентах (т.е. на 20% темнее) в PHP?
У меня есть шестнадцатеричное значение некоторого цвета, например #202010
.
Как сгенерировать новый цвет, который светлее или темнее задан в процентах (т.е. на 20% темнее) в PHP?
Корректировка цвета на проценты, как в примере, приведенном Frxstrem, не идеальна.
Если ваш цвет черный (0,0,0 в RGB), вы будете умножаться на ноль, что не приведет к каким-либо изменениям. Если ваш цвет темно-серый (например, 2,2,2 в RGB), вам нужно будет осветлить на 50%, чтобы просто подняться до (3,3,3). С другой стороны, если у вас есть цвет RGB (100,100,100), настройка на 50% сдвинет вас до (150 150 150), что значительно больше в сравнении.
Лучшим решением было бы настроить шаг/число (0-255) вместо процента, например, так (PHP-код):
Изменить 2014-01-06: немного очистил код.
function adjustBrightness($hex, $steps) {
// Steps should be between -255 and 255. Negative = darker, positive = lighter
$steps = max(-255, min(255, $steps));
// Normalize into a six character long hex string
$hex = str_replace('#', '', $hex);
if (strlen($hex) == 3) {
$hex = str_repeat(substr($hex,0,1), 2).str_repeat(substr($hex,1,1), 2).str_repeat(substr($hex,2,1), 2);
}
// Split into three parts: R, G and B
$color_parts = str_split($hex, 2);
$return = '#';
foreach ($color_parts as $color) {
$color = hexdec($color); // Convert to decimal
$color = max(0,min(255,$color + $steps)); // Adjust color
$return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
}
return $return;
}
Вот пример:
<?php
$color = '#aabbcc'; // The color we'll use
Извлеките цвета. Я бы предпочел использовать регулярные выражения, хотя есть и другие более эффективные способы.
if(!preg_match('/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i', $color, $parts))
die("Not a value color");
Теперь мы имеем красный цвет в $parts[1]
, зеленый в $parts[2]
и синий в $parts[3]
. Теперь, пусть преобразовать их из шестнадцатеричного в целые числа:
$out = ""; // Prepare to fill with the results
for($i = 1; $i <= 3; $i++) {
$parts[$i] = hexdec($parts[$i]);
Затем мы уменьшим их на 20%:
$parts[$i] = round($parts[$i] * 80/100); // 80/100 = 80%, i.e. 20% darker
// Increase or decrease it to fit your needs
Теперь мы вернем их в шестнадцатеричные и добавим их в нашу строку вывода
$out .= str_pad(dechex($parts[$i]), 2, '0', STR_PAD_LEFT);
}
Затем просто добавьте "#" в начало строки и это!
Ответы неправильные.
Использование модели RGB является концептуальной ошибкой.
Вам нужно преобразовать цвет из RGB (или Hex-формы) в HSL.
Это оттенок, насыщенность, легкость.
Как только вы конвертируете его из RGB в HSL, чтобы облегчить цвет, вы просто корректируете значение L (легкость) на 10%. Затем, как только вы закончите, вы конвертируете обратно из HSL в RGB, и все готово.
Voila!
Ответ Torkil Johnsen основан на фиксированном шаге, который не только манипулирует яркостью, но и слегка меняет оттенок. У метода Frxstrem также есть недостатки, как отметил Торкил Йонсен.
Я взял этот подход из комментария Github и улучшил код. Это отлично работает для любого случая.
/**
* Increases or decreases the brightness of a color by a percentage of the current brightness.
*
* @param string $hexCode Supported formats: '#FFF', '#FFFFFF', 'FFF', 'FFFFFF'
* @param float $adjustPercent A number between -1 and 1. E.g. 0.3 = 30% lighter; -0.4 = 40% darker.
*
* @return string
*/
function adjustBrightness($hexCode, $adjustPercent) {
$hexCode = ltrim($hexCode, '#');
if (strlen($hexCode) == 3) {
$hexCode = $hexCode[0] . $hexCode[0] . $hexCode[1] . $hexCode[1] . $hexCode[2] . $hexCode[2];
}
$hexCode = array_map('hexdec', str_split($hexCode, 2));
foreach ($hexCode as & $color) {
$adjustableLimit = $adjustPercent < 0 ? $color : 255 - $color;
$adjustAmount = ceil($adjustableLimit * $adjustPercent);
$color = str_pad(dechex($color + $adjustAmount), 2, '0', STR_PAD_LEFT);
}
return '#' . implode($hexCode);
}
Вот пример результата:
Мне это было интересно, но я спросил, как добавить непрозрачность к цвету?
Я хотел, чтобы цвет исчезал, а не светлее. я нашел это: http://www.gidnetwork.com/b-135.html и он отлично поработал с исходным сайтом для читателей SO.
function color_blend_by_opacity( $foreground, $opacity, $background=null )
{
static $colors_rgb=array(); // stores colour values already passed through the hexdec() functions below.
$foreground = str_replace('#','',$foreground);
if( is_null($background) )
$background = 'FFFFFF'; // default background.
$pattern = '~^[a-f0-9]{6,6}$~i'; // accept only valid hexadecimal colour values.
if( [email protected]_match($pattern, $foreground) or [email protected]_match($pattern, $background) )
{
trigger_error( "Invalid hexadecimal colour value(s) found", E_USER_WARNING );
return false;
}
$opacity = intval( $opacity ); // validate opacity data/number.
if( $opacity>100 || $opacity<0 )
{
trigger_error( "Opacity percentage error, valid numbers are between 0 - 100", E_USER_WARNING );
return false;
}
if( $opacity==100 ) // $transparency == 0
return strtoupper( $foreground );
if( $opacity==0 ) // $transparency == 100
return strtoupper( $background );
// calculate $transparency value.
$transparency = 100-$opacity;
if( !isset($colors_rgb[$foreground]) )
{ // do this only ONCE per script, for each unique colour.
$f = array( 'r'=>hexdec($foreground[0].$foreground[1]),
'g'=>hexdec($foreground[2].$foreground[3]),
'b'=>hexdec($foreground[4].$foreground[5]) );
$colors_rgb[$foreground] = $f;
}
else
{ // if this function is used 100 times in a script, this block is run 99 times. Efficient.
$f = $colors_rgb[$foreground];
}
if( !isset($colors_rgb[$background]) )
{ // do this only ONCE per script, for each unique colour.
$b = array( 'r'=>hexdec($background[0].$background[1]),
'g'=>hexdec($background[2].$background[3]),
'b'=>hexdec($background[4].$background[5]) );
$colors_rgb[$background] = $b;
}
else
{ // if this FUNCTION is used 100 times in a SCRIPT, this block will run 99 times. Efficient.
$b = $colors_rgb[$background];
}
$add = array( 'r'=>( $b['r']-$f['r'] ) / 100,
'g'=>( $b['g']-$f['g'] ) / 100,
'b'=>( $b['b']-$f['b'] ) / 100 );
$f['r'] += intval( $add['r'] * $transparency );
$f['g'] += intval( $add['g'] * $transparency );
$f['b'] += intval( $add['b'] * $transparency );
return sprintf( '%02X%02X%02X', $f['r'], $f['g'], $f['b'] );
}
https://github.com/mikeemoo/ColorJizz-PHP позволяет конвертировать в HSL, изменять компонент легкости и преобразовывать обратно в RGB.
Если вы хотите простую реализацию и вас не очень заботит то, чтобы значения были выше 50% яркости (или любого вашего порога), вы можете использовать мое решение для более светлых цветов:
$color = sprintf('#%06X', mt_rand(0xFFFFFF / 1.5, 0xFFFFFF));
Идея состоит в том, чтобы генерировать случайный цвет в верхней части палитры. Вы можете настроить результаты, чтобы они были более или менее темными, изменив значение "1,5":
Вы можете сделать то же самое для более темных цветов, установив начальную точку случайной функции на "0x000000" и разделив конечный предел:
$color = sprintf('#%06X', mt_rand(0x000000, 0xFFFFFF / 1.5));
Я знаю, что это не точно, но это работает для меня.