Программно осветлить или затемнить шестнадцатеричный цвет (или rgb и смешать цвета)

вот функция, над которой я работал, чтобы программно осветлить или затемнить шестнадцатеричный цвет на определенную сумму. Просто передайте строку, как "3F6D2A" цвета (col) и целое число base10 (amt) для количества, чтобы осветлить или затемнить. Чтобы затемнить, введите отрицательное число (т. е. -20).

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

function LightenDarkenColor(col,amt) {
    col = parseInt(col,16);
    return (((col & 0x0000FF) + amt) | ((((col>> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16)).toString(16);
}

для разработки используйте здесь более легкую для чтения версию:

function LightenDarkenColor(col,amt) {
    var num = parseInt(col,16);
    var r = (num >> 16) + amt;
    var b = ((num >> 8) & 0x00FF) + amt;
    var g = (num & 0x0000FF) + amt;
    var newColor = g | (b << 8) | (r << 16);
    return newColor.toString(16);
}

и, наконец, версия для обработки цветов, которые могут (или не могут) иметь знак "#" в начале. Плюс регулировка для неправильных значений цвета:

function LightenDarkenColor(col,amt) {
    var usePound = false;
    if ( col[0] == "#" ) {
        col = col.slice(1);
        usePound = true;
    }

    var num = parseInt(col,16);

    var r = (num >> 16) + amt;

    if ( r > 255 ) r = 255;
    else if  (r < 0) r = 0;

    var b = ((num >> 8) & 0x00FF) + amt;

    if ( b > 255 ) b = 255;
    else if  (b < 0) b = 0;

    var g = (num & 0x0000FF) + amt;

    if ( g > 255 ) g = 255;
    else if  ( g < 0 ) g = 0;

    return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}

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

если вы не используете"#", вы можете просто добавить его в код, например:

var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);

думаю, мой главный вопрос в том, прав ли я здесь? Разве это не относится к некоторым (нормальным) ситуациям?

11 ответов


TL; DR? --хотите просто осветлить / затемнить (затенение)? Перейдите к версии 2, Выберите один для RGB или Hex. -- Хотите полнофункциональный шейдер / блендер / конвертер с errorcheck и альфа и 3-значный шестнадцатеричный? Используйте версию 3 внизу.

играть с версии 3.1: jsfiddle > пример shadeBlendConvert

версия 3.1 на GitHub: Goto GitHub > PJs > pSBC


после некоторых обдумывающий... Я решил сам ответить на свой вопрос. Полтора года спустя. Это было действительно приключение с идеями от нескольких полезных пользователей, и я благодарю вас всех! Это для команды! Хотя это не обязательно ответ, который я искал. Потому что если то, что говорит Джеймс кури, правда, то в javascript нет истинной шестнадцатеричной математики, я должен использовать десятичные дроби, это двойное преобразование необходимо. Если мы сделаем это предположение, то это, вероятно, самый быстрый способ, который я видел (или могу придумать), чтобы осветлить (добавить белый) или затемнить (добавить черный) произвольный цвет RBG в процентах. Это также объясняет проблемы, упомянутые в его ответе на этот вопрос (он заполняет 0s). Но эта версия вызывает toString только один раз. Это также относится к вне диапазона (он будет применять 0 и 255 в качестве ограничений).

но будьте осторожны, вход цвета должен быть ровно 7 символов, как #08a35c. (или 6, Если используется верхняя версия)

спасибо Пабло за вдохновение и идею для использования процент. Для этого я сохраню имя функции одинаковым! лол! Однако этот отличается, поскольку он нормализует процент до 255 и, таким образом, добавляет одинаковое количество к каждому цвету (больше белого). Если вы проходите в 100 для percent это сделает ваш цвет чисто белый. Если вы передадите 0 для percent ничего не будет. Если вы проходите в 1 для percent он добавит 3 оттенка ко всем цветам (2,55 оттенка на 1%, округлые). Таким образом, вы действительно передаете процент белого (или черного, используйте отрицательный). Таким образом, эта версия позволяет осветлить чистый красный (FF0000), например.

я также использовал insight из ответа кита Машинтера на этот вопрос:как преобразовать decimal в hex в JavaScript?

я удалил некоторые, казалось бы, ненужные скобки. (как в двойном тернарном операторе и в крафте G) не уверен, что это будет мешать приоритету оператора в некоторых средах. Протестировано хорошо в FireFox.

function shadeColor1(color, percent) {  // deprecated. See below.
    var num = parseInt(color,16),
    amt = Math.round(2.55 * percent),
    R = (num >> 16) + amt,
    G = (num >> 8 & 0x00FF) + amt,
    B = (num & 0x0000FF) + amt;
    return (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
}

или, если вы хотите, чтобы он обрабатывал"#":

function shadeColor1(color, percent) {  // deprecated. See below.
    var num = parseInt(color.slice(1),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt;
    return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
}

как это для двух строк кода?

EDIT: исправить b g swap goof. Спасибо свачалек!


-- UPDATE-Версия 2 с смешиванием --

чуть больше года спустя, снова, и все еще продолжается. Но на этот раз, думаю, дело сделано. Отмечая проблемы, упомянутые о не использовании HSL для правильного осветления цвета. Существует метод, который устраняет большую часть этой неточности без необходимости конвертировать в HSL. Главная проблема заключается в том, что цветовой канал будет полностью насыщен, прежде чем остальные цвета. Вызывает изменение оттенка после этой точки. Я нашел эти вопросы здесь, здесь и здесь что привело меня в нужное русло. сообщение Марка Рэнсома показал мне разницу, и Кит показал мне путь. Лерп-Спаситель. Это то же самое, что и смешивание цветов, поэтому я создал там было больше adoing делать:

const shadeBlendConvert = function (p, from, to) {
    if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(to&&typeof(to)!="string"))return null; //ErrorCheck
    if(!this.sbcRip)this.sbcRip=(d)=>{
        let l=d.length,RGB={};
        if(l>9){
            d=d.split(",");
            if(d.length<3||d.length>4)return null;//ErrorCheck
            RGB[0]=i(d[0].split("(")[1]),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
        }else{
            if(l==8||l==6||l<4)return null; //ErrorCheck
            if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:""); //3 or 4 digit
            d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=-1;
            if(l==9||l==5)RGB[3]=r((RGB[2]/255)*10000)/10000,RGB[2]=RGB[1],RGB[1]=RGB[0],RGB[0]=d>>24&255;
        }
    return RGB;}
    var i=parseInt,r=Math.round,h=from.length>9,h=typeof(to)=="string"?to.length>9?true:to=="c"?!h:false:h,b=p<0,p=b?p*-1:p,to=to&&to!="c"?to:b?"#000000":"#FFFFFF",f=this.sbcRip(from),t=this.sbcRip(to);
    if(!f||!t)return null; //ErrorCheck
    if(h)return "rgb"+(f[3]>-1||t[3]>-1?"a(":"(")+r((t[0]-f[0])*p+f[0])+","+r((t[1]-f[1])*p+f[1])+","+r((t[2]-f[2])*p+f[2])+(f[3]<0&&t[3]<0?")":","+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*10000)/10000:t[3]<0?f[3]:t[3])+")");
    else return "#"+(0x100000000+r((t[0]-f[0])*p+f[0])*0x1000000+r((t[1]-f[1])*p+f[1])*0x10000+r((t[2]-f[2])*p+f[2])*0x100+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*255):t[3]>-1?r(t[3]*255):f[3]>-1?r(f[3]*255):255)).toString(16).slice(1,f[3]>-1||t[3]>-1?undefined:-2);
}

играть с версии 3.1: jsfiddle > пример shadeBlendConvert

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

все старые функции из v2 выше все еще должны быть здесь. Я попытался проверить все это, пожалуйста, напишите комментарий, если вы найдете что-то не так. Во всяком случае, вот новые возможности:

  • принимает 3-значные (или 4-значные) шестнадцатеричные цветовые коды в форме #RGB (или #ARGB). Это расширит их. удалить строку, помеченную //3 digit удалить эту функцию.
  • принимает и смешивает Альфа-каналы. Если from цвета или to цвета имеет альфа-канал, то результат будет иметь альфа-канал. Если оба цвета имеют альфа-канал, результатом будет сочетание двух альфа-каналов с использованием заданного процента (как если бы это был обычный цветовой канал). Если только один из двух цветов имеет альфа-канал, эта Альфа будет просто передана через результат. Это позволяет смешивать / оттенять прозрачный цвет, сохраняя при этом прозрачный уровень. Или, если прозрачный уровень должен смешать также, то сделайте конечно, у обоих цветов есть Альфы. Затенение пройдет через Альфа-канал, если вы хотите базовое затенение, которое также смешивает альфа-канал, используйте rgb(0,0,0,1) или rgb(255,255,255,1) в своем to цвета (или их шестнадцатеричные эквиваленты). Для цветов RGB результирующий альфа-канал будет округлен до 4 знаков после запятой.
  • преобразования RGB2Hex и Hex2RGB теперь неявны при использовании смешивания. Цвет результата всегда будет в виде to цвет, если он существует. Если нет to цвет, затем пройти 'c' в качестве to цвет, и он будет оттенять и конвертировать. Если требуется только преобразование, то pass 0 в процентах, а также.
  • вторичная функция также добавляется к глобальной. sbcRip может быть передан цвет hex или rbg, и он возвращает объект, содержащий эту информацию о цвете. Его в виде: {0:R,1:G,2:B,3:A}. Где R G и B есть ряд 0 to 255. И когда нет Альфы ... : A и -1. Иначе: A имеет ряд 0.0000 to 1.0000.
  • добавлена незначительная проверка ошибок. Это не идеально. Он все еще может разбиться. Но он поймает кое-что. В принципе, если структура в чем-то неверна или если процент не является числом или выходит за рамки, она вернет null. Пример: shadeBlendConvert(0.5,"salt") = null , где как он думает #salt является допустимым цветом. удалить четыре строки, помеченные //ErrorCheck чтобы удалить это особенность.

использования:

let color1 = "rgb(20,60,200)";
let color2 = "rgba(20,60,200,0.67423)";
let color3 = "#67DAF0";
let color4 = "#5567DAF0";
let color5 = "#F3A";
let color6 = "#F3A9";
let color7 = "rgb(200,60,20)";
let color8 = "rgba(200,60,20,0.98631)";
let c;

// Shade (Lighten or Darken)
c = shadeBlendConvert ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
c = shadeBlendConvert ( -0.4, color5 ); // #F3A + [40% Darker] => #991f66
c = shadeBlendConvert ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)
// Shade with Conversion (use "c" as your "to" color)
c = shadeBlendConvert ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac
// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
c = shadeBlendConvert ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)
// Blending
c = shadeBlendConvert ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.8303)
c = shadeBlendConvert ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
c = shadeBlendConvert ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
c = shadeBlendConvert ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9
// Error Checking
c = shadeBlendConvert ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
c = shadeBlendConvert ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
c = shadeBlendConvert ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
c = shadeBlendConvert ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
c = shadeBlendConvert ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)
// Error Check Fails (Some Errors are not Caught)
c = shadeBlendConvert ( 0.42, "#salt" ); // #salt + [42% Lighter] => #6b6b6b00  (...and a Pound of Salt is Jibberish)
// Ripping
c = sbcRip ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'0':85,'1':103,'2':218,'3':0.9412}

теперь я не решаюсь назвать это сделанным... снова...

PT

-- EDIT: Переключенная версия 3 для использования let, и функция стрелки, и добавлено this to sbcRip звонки.

----======----

мне так стыдно! (и удивлен, что никто не упомянул об этом) по-видимому, я не использую Альфа-каналы в своих собственных проектах... И... очевидно, я провел ужасное тестирование. Версия 3 не читала и не писала цвета с альфа-каналами правильно. Было несколько моментов, которые я либо просто ошибся, либо так и не узнал:

  • шестнадцатеричные цвета с Альфой - #RGBA (не #ARGB). Версия 3 читала и писала это задом наперед.
  • RGB цвета с альфами должны be rgba(), а не rgb(); версия 3 никогда не выводить rgba().
  • версия 3 не принять rgba() но приняли Альфы в rgb(), чего не должно произойти.

я сейчас заменена версия 3 на версию 3.1, где эти проблемы решаются. Я не размещал его как отдельную функцию здесь; видя, что старая версия 3 должна быть удалена из существования и заменена этой. Вот что я сделал. Версия 3 выше, на самом деле версия 3.1.

все старые функции сверху все еще здесь с этими обновления:

  • правильно читает и пишет цвета с альфа-каналами. И Hex, и RGB.
  • на to color теперь принимает цвет строки или falsy (который все еще может быть undefined).
  • функция теперь постоянна.

... Я рад, что не решился повторить. И вот мы здесь, еще год или около того спустя ... все еще совершенствуется...

PT


Я сделал решение, которое работает очень хорошо для меня:

function shadeColor(color, percent) {

    var R = parseInt(color.substring(1,3),16);
    var G = parseInt(color.substring(3,5),16);
    var B = parseInt(color.substring(5,7),16);

    R = parseInt(R * (100 + percent) / 100);
    G = parseInt(G * (100 + percent) / 100);
    B = parseInt(B * (100 + percent) / 100);

    R = (R<255)?R:255;  
    G = (G<255)?G:255;  
    B = (B<255)?B:255;  

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return "#"+RR+GG+BB;
}

Пример Осветлить:

shadeColor("#63C6FF",40);

Пример Даркен:

shadeColor("#63C6FF",-40);

я попробовал вашу функцию, и была небольшая ошибка: если какое-то окончательное значение " r "только 1 цифра, результат появляется как: "a0a0a", когда правильное значение "0a0a0a", например. Я просто быстро исправил это, добавив это вместо вашего возврата:

var rStr = (r.toString(16).length < 2)?'0'+r.toString(16):r.toString(16);
var gStr = (g.toString(16).length < 2)?'0'+g.toString(16):g.toString(16);
var bStr = (b.toString(16).length < 2)?'0'+b.toString(16):b.toString(16);

return (usePound?"#":"") + rStr + gStr + bStr;

может быть, это не так приятно, но это. Отличная функция, кстати. Как раз то, что мне нужно. :)


вы думали о преобразовании rgb > hsl? тогда просто двигайте светимость вверх и вниз? вот так я бы пошел.

быстрый поиск некоторых алгоритмов дал мне следующие сайты.

в PHP: http://serennu.com/colour/rgbtohsl.php

Яваскрипт: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

редактировать в выше ссылка больше не действительна. Вы можете просмотреть Git hub для исходный код страницы или суть

другой сайте StackOverflow вопрос может быть хорошее место, чтобы посмотреть.


хотя это не правильный выбор для OP, следующее является приближением кода, который я изначально предлагал. (Предполагая, что у вас есть функции преобразования rgb/hsl)

var SHADE_SHIFT_AMOUNT = 0.1; 

function lightenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.min(hsl[2] + SHADE_SHIFT_AMOUNT, 1);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

function darkenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.max(hsl[2] - SHADE_SHIFT_AMOUNT, 0);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

этот предполагает:

  1. у вас есть функции hslToRgb и rgbToHsl.
  2. параметр colorValue - это строка в форме #в rrggbb

хотя если мы обсуждаем CSS есть синтаксис для указания hsl / hsla для IE9 / Chrome / Firefox.


Это то, что я использовал на основе функции. Я предпочитаю использовать шаги над процентом, потому что это более интуитивно для меня.

например, 20% от 200 синего значения сильно отличается от 20% от 40 синего значения.

в любом случае, вот моя модификация, спасибо за вашу первоначальную функцию.

function adjustBrightness(col, amt) {

    var usePound = false;

    if (col[0] == "#") {
        col = col.slice(1);
        usePound = true;
    }

    var R = parseInt(col.substring(0,2),16);
    var G = parseInt(col.substring(2,4),16);
    var B = parseInt(col.substring(4,6),16);

    // to make the colour less bright than the input
    // change the following three "+" symbols to "-"
    R = R + amt;
    G = G + amt;
    B = B + amt;

    if (R > 255) R = 255;
    else if (R < 0) R = 0;

    if (G > 255) G = 255;
    else if (G < 0) G = 0;

    if (B > 255) B = 255;
    else if (B < 0) B = 0;

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return (usePound?"#":"") + RR + GG + BB;

}

следующий метод позволит вам осветлить или затемнить значение экспозиции в шестнадцатеричном (hex) цвет строки:

private static string GetHexFromRGB(byte r, byte g, byte b, double exposure)
{
    exposure = Math.Max(Math.Min(exposure, 1.0), -1.0);
    if (exposure >= 0)
    {
        return "#"
            + ((byte)(r + ((byte.MaxValue - r) * exposure))).ToString("X2")
            + ((byte)(g + ((byte.MaxValue - g) * exposure))).ToString("X2")
            + ((byte)(b + ((byte.MaxValue - b) * exposure))).ToString("X2");
    }
    else
    {
        return "#"
            + ((byte)(r + (r * exposure))).ToString("X2")
            + ((byte)(g + (g * exposure))).ToString("X2")
            + ((byte)(b + (b * exposure))).ToString("X2");
    }

}

для последнего значения параметра в GetHexFromRGB () передайте двойное значение где-то между -1 и 1 (-1 черный, 0 не изменяется, 1 белый):

// split color (#e04006) into three strings
var r = Convert.ToByte("e0", 16);
var g = Convert.ToByte("40", 16);
var b = Convert.ToByte("06", 16);

GetHexFromRGB(r, g, b, 0.25);  // Lighten by 25%;

Я хотел изменить цвет конкретные уровень яркости-независимо от того, какая яркость цвета была раньше-вот простая функция JS, которая, кажется, работает хорошо, хотя я уверен, что она может быть короче

function setLightPercentage(col: any, p: number) {
    const R = parseInt(col.substring(1, 3), 16);
    const G = parseInt(col.substring(3, 5), 16);
    const B = parseInt(col.substring(5, 7), 16);
    const curr_total_dark = (255 * 3) - (R + G + B);

    // calculate how much of the current darkness comes from the different channels
    const RR = ((255 - R) / curr_total_dark);
    const GR = ((255 - G) / curr_total_dark);
    const BR = ((255 - B) / curr_total_dark);

    // calculate how much darkness there should be in the new color
    const new_total_dark = ((255 - 255 * (p / 100)) * 3);

    // make the new channels contain the same % of available dark as the old ones did
    const NR = 255 - Math.round(RR * new_total_dark);
    const NG = 255 - Math.round(GR * new_total_dark);
    const NB = 255 - Math.round(BR * new_total_dark);

    const RO = ((NR.toString(16).length === 1) ? "0" + NR.toString(16) : NR.toString(16));
    const GO = ((NG.toString(16).length === 1) ? "0" + NG.toString(16) : NG.toString(16));
    const BO = ((NB.toString(16).length === 1) ? "0" + NB.toString(16) : NB.toString(16));

    return "#" + RO + GO + BO;}

C# Версии... обратите внимание, что я получаю цветные строки в этом формате #FF12AE34 и должен вырезать #FF.

    private string GetSmartShadeColorByBase(string s, float percent)
    {
        if (string.IsNullOrEmpty(s))
            return "";
        var r = s.Substring(3, 2);
        int rInt = int.Parse(r, NumberStyles.HexNumber);
        var g = s.Substring(5, 2);
        int gInt = int.Parse(g, NumberStyles.HexNumber);
        var b = s.Substring(7, 2);
        int bInt = int.Parse(b, NumberStyles.HexNumber);

        var t = percent < 0 ? 0 : 255;
        var p = percent < 0 ? percent*-1 : percent;

        int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
        var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
        var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);

        return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
    }

как простой цвет оттенка в PHP?

<?php
function shadeColor ($color='#cccccc', $percent=-25) {

  $color = Str_Replace("#",Null,$color);

  $r = Hexdec(Substr($color,0,2));
  $g = Hexdec(Substr($color,2,2));
  $b = Hexdec(Substr($color,4,2));

  $r = (Int)($r*(100+$percent)/100);
  $g = (Int)($g*(100+$percent)/100);
  $b = (Int)($b*(100+$percent)/100);

  $r = Trim(Dechex(($r<255)?$r:255));  
  $g = Trim(Dechex(($g<255)?$g:255));  
  $b = Trim(Dechex(($b<255)?$b:255));

  $r = ((Strlen($r)==1)?"0{$r}":$r);
  $g = ((Strlen($g)==1)?"0{$g}":$g);
  $b = ((Strlen($b)==1)?"0{$b}":$b);

  return (String)("#{$r}{$g}{$b}");
}

echo shadeColor(); // #999999

Я сделал порт отличной библиотеки xcolor, чтобы удалить ее зависимость jQuery. Там есть тонна функций, включая осветление и Затемнение цветов.

действительно, преобразование hex в RGB-это совершенно отдельная функция от осветления или затемнения цветов. Держите вещи сухими, пожалуйста. В любом случае, как только у вас есть цвет RGB, вы можете просто добавить разницу между уровнем света, который вы хотите, и уровнем света, который у вас есть, к каждому из RGB значения:

var lightness = function(level) {
    if(level === undefined) {
        return Math.max(this.g,this.r,this.b)
    } else {
        var roundedLevel = Math.round(level) // fractions won't work here
        var levelChange = roundedLevel - this.lightness()

        var r = Math.max(0,this.r+levelChange)
        var g = Math.max(0,this.g+levelChange)
        var b = Math.max(0,this.b+levelChange)

        if(r > 0xff) r = 0xff
        if(g > 0xff) g = 0xff
        if(b > 0xff) b = 0xff

        return xolor({r: r, g: g, b: b})
    }
}

var lighter = function(amount) {
    return this.lightness(this.lightness()+amount)
}

см.https://github.com/fresheneesz/xolor Для больше из источника.


Я давно хотел иметь возможность создавать оттенки / оттенки цветов, вот мое решение JavaScript:

const varyHue = function (hueIn, pcIn) {
    const truncate = function (valIn) {
        if (valIn > 255) {
            valIn = 255;
        } else if (valIn < 0)  {
            valIn = 0;
        }
        return valIn;
    };

    let red   = parseInt(hueIn.substring(0, 2), 16);
    let green = parseInt(hueIn.substring(2, 4), 16);
    let blue  = parseInt(hueIn.substring(4, 6), 16);
    let pc    = parseInt(pcIn, 10);    //shade positive, tint negative
    let max   = 0;
    let dif   = 0;

    max = red;

    if (pc < 0) {    //tint: make lighter
        if (green < max) {
            max = green;
        }

        if (blue < max) {
            max = blue;
        }

        dif = parseInt(((Math.abs(pc) / 100) * (255 - max)), 10);

        return leftPad(((truncate(red + dif)).toString(16)), '0', 2)  + leftPad(((truncate(green + dif)).toString(16)), '0', 2) + leftPad(((truncate(blue + dif)).toString(16)), '0', 2);
    } else {    //shade: make darker
        if (green > max) {
            max = green;
        }

        if (blue > max) {
            max = blue;
        }

        dif = parseInt(((pc / 100) * max), 10);

        return leftPad(((truncate(red - dif)).toString(16)), '0', 2)  + leftPad(((truncate(green - dif)).toString(16)), '0', 2) + leftPad(((truncate(blue - dif)).toString(16)), '0', 2);
    }
};