【问题标题】:How to generate lighter/darker color with PHP?如何使用 PHP 生成较浅/较深的颜色?
【发布时间】:2011-03-31 13:13:14
【问题描述】:

我有一些颜色的十六进制值,例如#202010

如何在 PHP 中以百分比(即暗 20%) 生成一种更亮或更暗的新颜色?

【问题讨论】:

  • 您已经问过这个问题,最好尝试实施您提供的 Javascript 解决方案,并对该问题发表更多评论,而不是开始一个新问题。
  • 如果您是为 web 应用程序/站点执行此操作,我认为使用 LESS 或 SASS 和 CSS 或 javascript 方法将是更有效的解决方案。但我的观点可能会有所偏差,因为我更喜欢 PHP/node/C# 等...用于创建后端服务,以便前端技术与之交互,(而不是将它们混为一谈,如旧 ASP。 NET 如此痛苦地做了/做了)。
  • 即使在另一个问题中,他也要求 PHP/CSS - 而不是 Javascript。

标签: php html css colors


【解决方案1】:

这是一个例子:

<?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);
}

然后只需在字符串的开头添加一个“#”,就可以了!

【讨论】:

  • 为此,我只是在 $out = ""; 中添加了 '#'部分,所以它现在读取 $out = "#"; // 准备填充结果
【解决方案2】:

按照 Frxstrem 给出的示例按百分比调整颜色并不理想。

如果您的颜色是黑色(RGB 中的 0,0,0),您将乘以零,这根本不会产生任何变化。如果您的颜色是深灰色(例如 RGB 中的 2,2,2),则必须将颜色调亮 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;
}

【讨论】:

  • 谢谢!今天派上用场了。
  • 太棒了,我在我的 wordpress 主题中使用了这个!
  • 这些步骤不能简单地平等地添加到每个颜色值,因为这会改变您正在使用的颜色的阴影。为了保持相同的颜色阴影,这是所需的结果,它必须是 R、G 和 B 值的小数部分。这看起来像:$r = max(0,min(255,$r + ($r * ($steps / 255))));
  • 您对为什么乘以百分比是错误的解释恰好是当您将亮度 (HSB) 设置为可变并上下滑动滑块从暗到亮时 Photoshop 如何更改其颜色。试试看。设置 RGB=(127,127,1) 并且当您从 0 亮度到 100 亮度时,B 保持在 0-2 的范围内。
  • 谢谢!我刚刚更改了开头,因此您可以使用百分比而不是 -255 或 255。function adjustBrightness($hex, $percent, $darken = true) { $brightness = $darken ? -255 : 255; $steps = $percent*$brightness/100; …。用法:adjustBrightness('#c2002f', 10, false ) 这会使我的颜色变亮。
【解决方案3】:

答案是错误的。

使用 RGB 模型是一个概念错误。

您需要将颜色从 RGB(或 Hex 形式)转换为 HSL。

即色相、饱和度、明度。

将其从 RGB 转换为 HSL 后,要使颜色变亮,只需将 L 值(亮度)调整 10%。然后,一旦完成,您就可以从 HSL 转换回 RGB,然后就完成了。

瞧!

RGB to HSV in PHP

【讨论】:

    【解决方案4】:

    我对此很感兴趣,但我的问题是如何为颜色添加不透明度

    我想要一种褪色的颜色,而不是变浅的颜色。我找到了这个: 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( !@preg_match($pattern, $foreground)  or  !@preg_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'] );
    }
    

    【讨论】:

      【解决方案5】:

      https://github.com/mikeemoo/ColorJizz-PHP 允许转换为 HSL,更改亮度分量并转换回 RGB。

      【讨论】:

        【解决方案6】:

        如果您想要一个简单的实现,并且您不太关心亮度值是否特别高于 50%(或任何您的阈值),您可以使用我的解决方案来获得较浅的颜色:

        $color = sprintf('#%06X', mt_rand(0xFFFFFF / 1.5, 0xFFFFFF));
        

        这个想法是在调色板的较高部分生成随机颜色。您可以通过更改“1.5”值将结果调整为或多或少暗:

        • 更大会将调色板扩展为更深的颜色
        • 较小会将其限制为较浅的颜色

        您可以通过将随机函数的起点设置为“0x000000”并划分结束限制来对较深的颜色执行相同的操作:

        $color = sprintf('#%06X', mt_rand(0x000000, 0xFFFFFF / 1.5));
        

        我知道这并不精确,但它对我有用。

        【讨论】:

          【解决方案7】:

          Torkil Johnsen 的答案基于固定步长,它不仅控制亮度,还略微改变色调。正如 Torkil Johnsen 所指出的,Frxstrem 的方法也存在缺陷。

          我从Github comment 中采用了这种方法并改进了代码。它适用于任何情况。

          /**
           * 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
           *
           * @author  maliayas
           */
          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);
          }
          

          这是一个示例结果:

          【讨论】:

          • 太棒了!与 Kiran 的 TooLightYIQ(hexcolor) 函数配合得很好,这里:link
          • 这可能不是完美的颜色方式,但对于我的用例来说已经足够了,而且它更简单,只是一个简短的功能:)
          • 请注意,dechex 函数需要一个整数,上面的示例将提供一个浮点数。这将打破较新的 PHP 版本。
          猜你喜欢
          • 1970-01-01
          • 2013-07-21
          • 2010-09-10
          • 2018-02-17
          • 1970-01-01
          • 2012-07-11
          • 1970-01-01
          • 2017-07-12
          • 2012-11-29
          相关资源
          最近更新 更多