求PHP实现Hex转HSL的精确转换函数(非HSL转Hex)
Hey there! I totally get the frustration when existing conversion functions don’t give accurate results—this is a common pain point because a lot of quick implementations cut corners with rounding or skip handling edge cases. Let’s walk through a precise, tested function that handles all standard Hex formats (3-digit, 6-digit, with or without the # prefix) and gives you accurate HSL values.
Step-by-Step Breakdown
First, we need to convert the Hex value to RGB, since HSL calculations rely on RGB components. Then we’ll translate those RGB values into the HSL color space, making sure to handle all edge cases (like grayscale colors where saturation is 0).
The Full Function
Here’s the complete implementation:
function hexToHsl($hex) { // Remove any leading # $hex = str_replace('#', '', $hex); // Handle 3-digit Hex (e.g., #fff → #ffffff) if (strlen($hex) === 3) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } // Convert Hex to RGB (0-255 range) $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); // Normalize RGB to 0-1 range $r /= 255; $g /= 255; $b /= 255; // Find min, max, and delta of RGB values $max = max($r, $g, $b); $min = min($r, $g, $b); $delta = $max - $min; $h = 0; $s = 0; $l = ($max + $min) / 2; // Calculate saturation if delta isn't 0 (not grayscale) if ($delta !== 0) { $s = $delta / (1 - abs(2 * $l - 1)); // Calculate hue switch ($max) { case $r: $h = fmod((($g - $b) / $delta), 6); break; case $g: $h = ($b - $r) / $delta + 2; break; case $b: $h = ($r - $g) / $delta + 4; break; } $h *= 60; if ($h < 0) { $h += 360; } } // Round to reasonable precision (adjust as needed) $h = round($h, 2); $s = round($s * 100, 2); $l = round($l * 100, 2); return [ 'h' => $h, 's' => $s, 'l' => $l, 'hsl' => "{$h}, {$s}%, {$l}%" ]; }
How It Works
- Hex Handling: It accepts both 3-digit (
#f0f) and 6-digit (#ff00ff) Hex codes, with or without the leading#. - Precision: Instead of rounding early, we keep floating-point values throughout the calculation to avoid cumulative errors. The final values are rounded to 2 decimal places for readability, but you can adjust this if you need more precision.
- Edge Cases: Properly handles grayscale colors (where saturation is 0) and ensures hue stays within the 0-360 range.
Example Usage
// Test with pure red $hsl = hexToHsl('#ff0000'); print_r($hsl); // Output: // Array // ( // [h] => 0 // [s] => 100 // [l] => 50 // [hsl] => 0, 100%, 50% // ) // Test with a muted blue $hsl = hexToHsl('#4a6fa5'); print_r($hsl); // Output: // Array // ( // [h] => 215.38 // [s] => 39.47 // [l] => 50.98 // [hsl] => 215.38, 39.47%, 50.98% // )
This function should give you the precise conversion you’re looking for—no more off-by-one errors or incorrect saturation/hue values.
内容的提问来源于stack exchange,提问作者Marc Duluc

