PHP генерирует цвет RGB для объекта на основе уникального значения - PullRequest
0 голосов
/ 27 июня 2018

Я знаю, что об этом уже спрашивали, но мне нужно немного больше помощи, чем другие ответы на SO.

В настоящее время у меня есть цикл foreach, который перебирает записи в моей БД. Каждая строка содержит уникальный первичный атрибут «id» (1,2,3,4,5 и т. Д.).

В моем цикле мне нужно сгенерировать УНИКАЛЬНОЕ значение RGB для каждой записи на основе ее идентификатора. Полученное значение RGB будет применено к тексту HTML-элемента, привязанного к этой записи. Сгенерированный цвет должен быть уникальным для самой записи (через «id»), поэтому я не использую итератор цикла.

Я уже создал рабочую функцию, чтобы сделать это для меня, но мне нужно еще кое-что - мне нужно, чтобы значение rgb имело контрастность выше 4: 5: 1 на белом фоне. У меня есть функция, которая генерирует слишком яркие цвета, что затрудняет чтение текста. Как я могу изменить свою функцию, чтобы получить более темные цвета, которые хорошо контрастируют на белом фоне?

function makeRgbFromValue(int $value){
    $hash = md5($value);

    return implode(", ", [
        hexdec(substr($hash, 0, 2)), // r
        hexdec(substr($hash, 2, 2)), // g
        hexdec(substr($hash, 4, 2))  // b
    ]);
}

// Example output: "100, 201, 20"

// My html, using Laravel Blade syntax:

@foreach($categories as $cat)
    <a 
        href="/blog/channels/{{ $cat->slug }}"
        style="color: rgb(
           {{ makeRgbFromValue($cat->id) }}
        )"
    >
        {{ $cat->name }}
    </a>
@endforeach

Может быть, это невозможно ... но я надеюсь, что один из вас, математические гении, может мне помочь:)

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Хотя переводить очень сложно, вероятно, для этого лучше использовать цветовое пространство HSV. Мне нравится выбирать насыщенность [0.75 - это хорошо], а затем играть с оттенком и значением.

Отмена функции преобразования HSV / RGB из этой сущности :

function HSV_TO_RGB ($H, $S, $V) {
    $RGB = array(); 
    if($S == 0) { 
        $R = $G = $B = $V * 255; 
    } else { 
        $var_H = $H * 6; 
        $var_i = floor( $var_H ); 
        $var_1 = $V * ( 1 - $S ); 
        $var_2 = $V * ( 1 - $S * ( $var_H - $var_i ) ); 
        $var_3 = $V * ( 1 - $S * (1 - ( $var_H - $var_i ) ) ); 
        if       ($var_i == 0) { $var_R = $V     ; $var_G = $var_3  ; $var_B = $var_1 ; } 
        else if  ($var_i == 1) { $var_R = $var_2 ; $var_G = $V      ; $var_B = $var_1 ; } 
        else if  ($var_i == 2) { $var_R = $var_1 ; $var_G = $V      ; $var_B = $var_3 ; } 
        else if  ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2  ; $var_B = $V     ; } 
        else if  ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1  ; $var_B = $V     ; } 
        else                   { $var_R = $V     ; $var_G = $var_1  ; $var_B = $var_2 ; } 
        $R = $var_R * 255; 
        $G = $var_G * 255; 
        $B = $var_B * 255; 
    } 
    $RGB['R'] = $R; 
    $RGB['G'] = $G; 
    $RGB['B'] = $B; 
    return $RGB; 
}

А потом:

$fmt = '<span style="background-color: #%s" title="%s">%s</span>' . "\n";
$fill = str_repeat('&nbsp;', 5);

$S = 0.75;
for($i=0; $i<25; $i++) {
    $hash = md5(mt_rand());
    $H =   hexdec(substr($hash, 0, 2))/255;
    $V = ( hexdec(substr($hash, 2, 2))/255 ) / 2 + 0.5; // pick from the brighter half
    $rgb = implode('', array_map(
    function($a){
        return str_pad(dechex(intval($a)), 2, '0', STR_PAD_LEFT);
    }, HSV_TO_RGB($H, $S, $V)));
    printf($fmt, $rgb, sprintf("HSV(%0.2f,%0.2f,%0.2f)", $H, $S, $V), $fill);
}

Дает нам что-то вроде:

yay colored boxes!

0 голосов
/ 27 июня 2018

Вы можете рассчитать яркость:

function lumdiff($R1,$G1,$B1,$R2,$G2,$B2){
    $L1 = 0.2126 * pow($R1/255, 2.2) +
          0.7152 * pow($G1/255, 2.2) +
          0.0722 * pow($B1/255, 2.2);

    $L2 = 0.2126 * pow($R2/255, 2.2) +
          0.7152 * pow($G2/255, 2.2) +
          0.0722 * pow($B2/255, 2.2);

    if($L1 > $L2){
        return ($L1+0.05) / ($L2+0.05);
    }else{
        return ($L2+0.05) / ($L1+0.05);
    }
}

Возвращаемое значение должно быть больше 5 для лучшей читаемости. Функция была найдена здесь

Но вы должны получить еще один символ из хэша, чтобы получить другой цвет, так что столкновение более вероятно.

function makeRgbFromValue($value){
    $hash = md5($value);
    $brightness = 0;
    $shift = 0;

    while($brightness < 5 && $shift<26) {
        $color = [
            hexdec(substr($hash, $shift, 2)), // r
            hexdec(substr($hash, $shift+2, 2)), // g
            hexdec(substr($hash, $shift+4, 2))  // b
        ];
        $brightness = lumdiff($color[0], $color[1], $color[2], 255,255,255);
        $shift++;
    }

    return implode(", ", $color);
}

Я считаю, что цвет будет найден в 25 циклах:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...