Secara terprogram mencerahkan atau menggelapkan warna hex (atau rgb, dan memadukan warna)


504

Berikut adalah fungsi yang sedang saya kerjakan untuk secara terprogram mencerahkan atau menggelapkan warna hex dengan jumlah tertentu. Cukup masukkan string seperti "3F6D2A"untuk warna ( col) dan integer base10 ( amt) untuk jumlah yang menjadi terang atau gelap. Untuk menggelapkan, berikan angka negatif (yaitu -20).

Alasan saya melakukan ini adalah karena semua solusi yang saya temukan, sejauh ini, mereka tampaknya terlalu memperumit masalah. Dan saya merasa itu bisa dilakukan hanya dengan beberapa baris kode. Harap beri tahu saya jika Anda menemukan masalah, atau lakukan penyesuaian apa pun untuk mempercepatnya.

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


// TEST
console.log( LightenDarkenColor("3F6D2A",40) );

Untuk Pengembangan, gunakan versi ini yang lebih mudah dibaca:

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


// TEST
console.log(LightenDarkenColor("3F6D2A", -40));

Dan akhirnya versi untuk menangani warna yang mungkin (atau mungkin tidak) memiliki "#" di awal. Ditambah penyesuaian untuk nilai warna yang tidak tepat:

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

OK, jadi sekarang ini bukan hanya beberapa baris, tetapi tampaknya jauh lebih sederhana dan jika Anda tidak menggunakan "#" dan tidak perlu memeriksa warna di luar jangkauan, itu hanya beberapa baris.

Jika tidak menggunakan "#", Anda bisa menambahkannya dalam kode seperti:

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

Saya kira pertanyaan utama saya adalah, apakah saya benar di sini? Apakah ini tidak mencakup beberapa situasi (normal)?


1
Jika Anda tidak mendapatkan hasil yang diharapkan saat memodifikasi warna, saya sarankan melihat ke ruang warna LAB, yang lebih dekat dengan visi manusia. Banyak bahasa memiliki perpustakaan untuk konversi. Dalam pengalaman saya terutama nuansa oranye bisa menjadi masalah saat gelap atau terang.
Henrik

Poin yang sangat bagus. Namun, tujuan utama dari pertanyaan ini adalah untuk menemukan, pertama, runtime tercepat dan formula ukuran terkecil ... dan kedua, keakuratannya. Karenanya, mengapa saya tidak berurusan dengan konversi ke HSL atau apa pun. Di sini kecepatan dan ukuran lebih penting. Tapi, seperti yang bisa Anda lihat dengan formula 2 versi saya. Menggunakan LERP untuk menaungi akan menghasilkan jeruk yang menyenangkan sepanjang rentang naungan. Lihatlah bagan warna di bawah ini dan beri tahu saya jika rentang warna tidak terlalu dekat dengan akurat sebenarnya.
Pimp Trizkit

Saya agak bingung dengan struktur di sini, tetapi Anda benar, tingkat oranye untuk shadeColor1 tampaknya sangat bagus.
Henrik

Lol, maksud Anda shadeColor2. Saya kira struktur yang Anda bicarakan adalah tata letak keseluruhan dari jawaban itu sendiri? Adakah petunjuk untuk membuatnya lebih jelas?
Pimp Trizkit

3
Hanya ada satu masalah dalam fungsi dengan # di atas adalah bahwa ia tidak menciptakan nol terkemuka jika kode hex terakhir dimulai dengan nol. Misalnya, jika kode heksnya adalah # 00a6b7 akan mengeluarkannya sebagai # a6b7, yang tidak akan berfungsi jika menggunakan sebagai css. Anda dapat memperbaikinya dengan mengganti baris kembali dengan ini: var string = "000000" + (g | (b << 8) | (r << 16)). ToString (16); return (usePound? "#": "") + string.substr (string.length-6);
Rafael Levy

Jawaban:


877

Nah, jawaban ini sudah menjadi binatang buas sendiri. Banyak versi baru, itu semakin lama bodoh. Terima kasih banyak untuk semua kontributor untuk jawaban ini. Tapi, agar tetap sederhana bagi massa. Saya mengarsipkan semua versi / sejarah evolusi jawaban ini ke github saya . Dan mulai membersihkannya di StackOverflow di sini dengan versi terbaru. Terima kasih khusus kepada Mike 'Pomax' Kamermans untuk versi ini. Dia memberiku matematika baru.


Fungsi ini ( pSBC) akan mengambil warna web HEX atau RGB. pSBCdapat menaungi lebih gelap atau lebih terang, atau mencampurnya dengan warna kedua, dan juga bisa meneruskannya melalui tetapi mengubah dari Hex ke RGB (Hex2RGB) atau RGB ke Hex (RGB2Hex). Semua tanpa Anda bahkan tahu format warna apa yang Anda gunakan.

Ini berjalan sangat cepat, mungkin yang tercepat, terutama mengingat banyak fiturnya. Sudah lama dalam pembuatan. Lihat keseluruhan cerita di github saya . Jika Anda ingin cara terkecil dan tercepat untuk menaungi atau menyatu, lihat Fungsi Mikro di bawah ini dan gunakan salah satu dari setan kecepatan 2-liner. Mereka bagus untuk animasi yang intens, tetapi versi ini cukup cepat untuk sebagian besar animasi.

Fungsi ini menggunakan Blending Log atau Linear Blending. Namun, itu TIDAK mengkonversi ke HSL untuk benar mencerahkan atau menggelapkan warna. Oleh karena itu, hasil dari fungsi ini akan berbeda dari fungsi yang jauh lebih besar dan lebih lambat yang menggunakan HSL.

jsFiddle dengan pSBC

github> pSBC Wiki

Fitur:

  • Mendeteksi otomatis dan menerima warna Hex standar dalam bentuk string. Misalnya: "#AA6622"atau "#bb551144".
  • Mendeteksi otomatis dan menerima warna RGB standar dalam bentuk string. Misalnya: "rgb(123,45,76)"atau "rgba(45,15,74,0.45)".
  • Nuansa warna menjadi putih atau hitam dengan persentase.
  • Memadukan warna bersama berdasarkan persentase.
  • Apakah konversi Hex2RGB dan RGB2Hex pada saat yang sama, atau solo.
  • Menerima kode warna HEX 3 digit (atau 4 digit w / alpha), dalam bentuk #RGB (atau #RGBA). Itu akan memperluas mereka. Sebagai Contoh: "#C41"menjadi "#CC4411".
  • Terima dan (Linear) memadukan saluran alfa. Jika salah satu c0(dari) warna atau c1(ke) warna memiliki saluran alpha, maka warna yang dikembalikan akan memiliki saluran alpha. Jika kedua warna memiliki saluran alfa, maka warna yang dikembalikan akan menjadi campuran linear dari dua saluran alfa menggunakan persentase yang diberikan (sama seperti jika itu merupakan saluran warna normal). Jika hanya satu dari dua warna yang memiliki saluran alpha, alpha ini hanya akan diteruskan ke warna yang dikembalikan. Ini memungkinkan seseorang untuk berbaur / menaungi warna transparan dengan tetap menjaga tingkat transparansi. Atau, jika tingkat transparansi juga harus berbaur, pastikan kedua warna memiliki alfas. Saat shading, itu akan melewati saluran alpha langsung melalui. Jika Anda ingin arsiran dasar yang juga menaungi saluran alpha, maka gunakan rgb(0,0,0,1)atau rgb(255,255,255,1)sebagaic1(untuk) warna (atau setara hex-nya). Untuk warna RGB, saluran alpha warna yang dikembalikan akan dibulatkan ke 3 tempat desimal.
  • Konversi RGB2Hex dan Hex2RGB tersirat saat menggunakan blending. Terlepas dari c0(dari) warna; warna yang dikembalikan akan selalu dalam format warna dari warna c1(ke), jika ada. Jika tidak ada c1warna (untuk), maka lewat 'c'sebagai c1warna dan itu akan menaungi dan mengubah apapun c0warnanya. Jika hanya konversi yang diinginkan, maka masukkan 0sebagai persentase ( p) juga. Jika c1warna dihilangkan atau tidak stringdilewatkan, itu tidak akan dikonversi.
  • Fungsi sekunder ditambahkan ke global juga. pSBCrdapat melewati warna Hex atau RGB dan mengembalikan objek yang berisi informasi warna ini. Ini dalam bentuk: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Di mana .r,, .gdan .bmemiliki rentang 0 hingga 255. Dan ketika tidak ada alfa: .aadalah -1. Jika tidak: .amemiliki rentang 0,000 hingga 1.000.
  • Untuk output RGB, output rgba()berakhir rgb()ketika warna dengan saluran alpha dilewatkan ke c0(dari) dan / atau c1(ke).
  • Pemeriksaan Kesalahan Kecil telah ditambahkan. Itu tidak sempurna. Itu masih bisa macet atau membuat bualan. Tapi itu akan menangkap beberapa hal. Pada dasarnya, jika strukturnya salah dalam beberapa hal atau jika persentase bukan angka atau di luar ruang lingkup, itu akan kembali null. Contoh:, pSBC(0.5,"salt") == nulldimana menurutnya #saltadalah warna yang valid. Hapus empat baris yang berakhir dengan return null;untuk menghapus fitur ini dan membuatnya lebih cepat dan lebih kecil.
  • Menggunakan Pencampuran Log. Pass truein for l(parameter ke-4) untuk menggunakan Linear Blending.

Kode:

// Version 4.0
const pSBC=(p,c0,c1,l)=>{
    let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
    if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
    if(!this.pSBCr)this.pSBCr=(d)=>{
        let n=d.length,x={};
        if(n>9){
            [r,g,b,a]=d=d.split(","),n=d.length;
            if(n<3||n>4)return null;
            x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
        }else{
            if(n==8||n==6||n<4)return null;
            if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
            d=i(d.slice(1),16);
            if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
            else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
        }return x};
    h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
    if(!f||!t)return null;
    if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
    else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
    a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
    if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
    else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
}

Pemakaian:

// Setup:

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)";

// Tests:

/*** Log Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(166,171,225)
pSBC ( -0.4, color5 ); // #F3A + [40% Darker] => #c62884
pSBC ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(225,171,166,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #a6abe1ac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(142,60,142,0.83)
pSBC ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(168,60,111,0.67423)
pSBC ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(134,191,208)
pSBC ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #86bfd0

/*** Linear Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1, false, true ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
pSBC ( -0.4, color5, false, true ); // #F3A + [40% Darker] => #991f66
pSBC ( 0.42, color8, false, true ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c", true ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c", true ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8, true ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.83)
pSBC ( 0.7, color2, color7, true ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
pSBC ( 0.25, color3, color7, true ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
pSBC ( 0.75, color7, color3, true ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9

/*** Other Stuff ***/
// Error Checking
pSBC ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
pSBC ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
pSBC ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
pSBC ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
pSBC ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)

// Error Check Fails (Some Errors are not Caught)
pSBC ( 0.42, "#salt" ); // #salt + [42% Lighter] => #a5a5a500  (...and a Pound of Salt is Jibberish)

// Ripping
pSBCr ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'r':85,'g':103,'b':218,'a':0.941}

Gambar di bawah ini akan membantu menunjukkan perbedaan dalam dua metode pencampuran:


Fungsi Mikro

Jika Anda benar-benar menginginkan kecepatan dan ukuran, Anda harus menggunakan RGB bukan HEX. RGB lebih mudah dan sederhana, HEX menulis terlalu lambat dan terlalu banyak rasa untuk dua-liner sederhana (IE. Ini bisa menjadi kode HEX 3, 4, 6, atau 8 digit). Anda juga perlu mengorbankan beberapa fitur, tidak ada pengecekan kesalahan, tidak ada HEX2RGB atau RGB2HEX. Selain itu, Anda harus memilih fungsi tertentu (berdasarkan nama fungsinya di bawah) untuk matematika pencampuran warna, dan jika Anda ingin shading atau blending. Fungsi-fungsi ini mendukung saluran alfa. Dan ketika kedua warna input memiliki alfas akan Linear Blend mereka. Jika hanya satu dari dua warna yang memiliki alfa, itu akan meneruskannya langsung ke warna yang dihasilkan. Di bawah ini adalah dua fungsi liner yang sangat cepat dan kecil:

const RGB_Linear_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+j;
}

const RGB_Linear_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:255*p,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
}

const RGB_Log_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,j=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+j;
}

const RGB_Log_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:p*255**2,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
}

Ingin info lebih lanjut? Baca artikel selengkapnya di github .

PT

(Ps Jika ada yang punya matematika untuk metode blending lain, silakan berbagi.)


8
Versi PHP untuk mereka yang membutuhkannya: gist.github.com/chaoszcat/5325115#file-gistfile1-php
Lionel Chan

28
Saya menggunakan TinyColor -tinycolor.darken(color,amount);
FWrnr

4
Pos hebat ... :) ... baru saja membuat ekstensi Swift: gist.github.com/matejukmar/1da47f7a950d1ba68a95
Matej Ukmar

2
Berikut adalah versi PHP untuk versi shadeColor2 yang diperbarui: function shadeColor2($color, $percent) { $color = str_replace("#", "", $color); $t=$percent<0?0:255; $p=$percent<0?$percent*-1:$percent; $RGB = str_split($color, 2); $R=hexdec($RGB[0]); $G=hexdec($RGB[1]); $B=hexdec($RGB[2]); return '#'.substr(dechex(0x1000000+(round(($t-$R)*$p)+$R)*0x10000+(round(($t-$G)*$p)+$G)*0x100+(round(($t-$B)*$p)+$B)),1); }
Kevin M

2
Maaf, sepertinya saya melewatkan titik itu. Mungkin ada dua alasan. Yang pertama dan jelas adalah bahwa saya menggunakan Math.Round dan Anda tidak bisa menggunakan angka desimal untuk pewarnaan yang akurat (warna tidak memiliki desimal dalam hex). Misalnya, jika saluran Merah 8, tambahkan 10%Anda mendapatkan 8.8putaran ke 9. Kemudian ambil 9.09%dari 9dan Anda dapatkan 8.1819. Yang bulat 8jadi itu contoh yang buruk. Tapi itu masih menggambarkan bahwa Anda mengambil 9.09%dari 9dan tidak 8.8. Jadi mungkin ada beberapa angka di sana yang tidak melengkapi persis sama dengan contoh saya di sini.
Pimp Trizkit

122

Saya membuat solusi yang bekerja sangat bagus untuk saya:

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

Contoh Meringankan:

shadeColor("#63C6FF",40);

Contoh Gelap:

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

4
Bagus, saya suka persentasenya! 1 Tho, saya akan mungkin melakukan R = ((R<255)?R:255).toString(16);itu R = R.length==1 ? "0"+R : Runtuk kecepatan. Dan saya tidak yakin titik toUpperCase?
Pimp Trizkit

Itu tidak perlu. Saya hanya menambahkan itu untuk cetak cantik saat pengujian. Saya akan mengeditnya.
Pablo

Sangat bagus. Namun, haruskah 100% lebih terang tidak menjadi sepenuhnya putih dan 100% gelap selalu hitam, tidak peduli warna apa? tampaknya -100 memang membuat warna hitam, tapi 100 (positif) tidak membuatnya sepenuhnya putih.
Kevin M

4
tidak bekerja dengan warna solid seperti # ff0000, # 00ff00, # 0000ff
Hitori

Untuk membuatnya bekerja dengan warna hitam, saya baru melakukan hack ini var R = parseInt(color.substring(1, 3), 16) var G = parseInt(color.substring(3, 5), 16) var B = parseInt(color.substring(5, 7), 16) if (R == 0) R = 32; if (G == 0) G = 32; if (B == 0) B = 32;
Irfan Raza

21

Ini adalah liner super sederhana berdasarkan jawaban Eric

function adjust(color, amount) {
    return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}

Contoh:

adjust('#ffffff', -20) => "#ebebeb"
adjust('000000', 20) => "#141414"

7
"super sederhana".
Andrew

5

Inilah yang saya gunakan berdasarkan fungsi Anda. Saya lebih suka menggunakan langkah daripada persentase karena lebih intuitif bagi saya.

Sebagai contoh, 20% dari nilai biru 200 jauh berbeda dari 20% dari nilai biru.

Bagaimanapun, ini modifikasi saya, terima kasih untuk fungsi asli Anda.

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;

}

Menemukan ini jauh lebih berguna daripada jawaban atas karena jawaban teratas adalah membuat warna saya sangat intens, bukan hanya lebih gelap. Cheers Eric
Worm

4

Saya mencoba fungsi Anda dan ada sedikit bug: Jika nilai akhir 'r' hanya 1 digit, hasilnya muncul seperti: 'a0a0a' ketika nilai yang tepat adalah '0a0a0a', misalnya. Saya hanya cepat memperbaikinya dengan menambahkan ini sebagai ganti pengembalian Anda:

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;

Mungkin itu tidak begitu baik tetapi itu berhasil. Fungsi hebat, BTW. Apa yang saya butuhkan. :)


1
Terima kasih atas debug dan pujiannya! Sayang sekali itu bukan jawaban apakah ada cara yang lebih cepat, yang merupakan pertanyaan utama saya. Seperti mungkin yang menggunakan semua konversi hex dan tanpa basis. Ya, saya kira Anda memberi tahu saya jika saya memiliki kode yang benar (+1). Sayangnya, perbaikannya menambahkan overhead yang jauh lebih banyak (sekarang panggilan Anda ke String 6 kali), dan KISS sedikit lebih sedikit. Mungkin akan lebih cepat untuk memeriksa apakah nomor base10 adalah 15 atau kurang, sebelum konversi base16. Tapi saya suka!
Pimp Trizkit

4

apakah Anda sudah memikirkan konversi rgb> hsl? lalu pindahkan Luminositas ke atas dan ke bawah? itulah cara saya akan pergi.

Sekilas untuk beberapa algoritma membuat saya situs berikut.

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

Javascript: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

Sunting tautan di atas tidak lagi valid. Anda dapat melihat hub git untuk sumber halaman atau inti

Atau pertanyaan StackOverflow lain mungkin tempat yang baik untuk mencari.


Meskipun ini bukan pilihan yang tepat untuk OP, berikut ini adalah perkiraan kode yang awalnya saya sarankan. (Dengan asumsi Anda memiliki fungsi konversi 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;
}

Ini mengasumsikan:

  1. Anda memiliki fungsi hslToRgbdanrgbToHsl .
  2. Parameternya colorValueadalah string dalam bentuk #RRGGBB

Meskipun jika kita membahas css ada sintaks untuk menentukan hsl / hsla untuk IE9 / Chrome / Firefox.


Menarik, tetapi kemudian tidakkah saya harus mengkonversi dari string hex ke rgb ke hsl? Sepertinya ini lebih rumit. Mungkin saya melewatkan sesuatu. Tapi, saya mencari cara KISS untuk melakukannya, serta secepat mungkin (waktu eksekusi). Saya merasa idealnya, jika saya bisa melakukan semuanya dalam hex yang akan menjadi yang tercepat. Tapi, solusi yang saya kembangkan di sini melibatkan pergi ke rgb untuk dapat menambahkan jumlah tambahan.
Pimp Trizkit

Ya saya menganggap itu akan lebih lambat, lebih rumit dan jika Anda tidak menggunakan konversi rgb ke hsl di tempat lain maka itu mungkin tidak akan menjadi solusi yang paling sederhana. Namun, itu akan lebih akurat daripada menambahkan nilai-nilai rgb meskipun saya sendiri tidak terlalu berkulit hitam. Itu semua tergantung pada seberapa akurat Anda ingin menjadi kurasa.
James Khoury

Apa kehilangan akurasi yang Anda sebutkan? Saya berasumsi maksud Anda semua warna [web] tidak dapat dijangkau dengan rgb atau apalah?
Pimp Trizkit

Seperti yang saya katakan, saya tidak tahu banyak tentang warna: wiki Color Theory
James Khoury

@Pimp Trizkit: Ini kurang akurat karena (dan ini hanya teoriku ... Saya bukan ahli warna) Anda menggeser setiap saluran dengan jumlah yang sama, tidak peduli berapa banyak warna yang ada untuk memulai. Saya pikir itu akan menghasilkan penurunan saturasi karena Anda membawa saluran lebih dekat satu sama lain (berdasarkan persentase). Tentu saja, jika Anda overflow / underflow itu tidak dapat dihindari pula.
Matthew Crumley

2

C # Version ... perhatikan bahwa saya mendapatkan string warna dalam format ini # FF12AE34, dan harus memotong #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);
    }

5
Tidak pernah menggunakan C # sebelumnya, tetapi sepertinya tiga deklarasi variabel terakhir adalah aneh. An intdan dua varsuntuk tipe data yang sama.
Pimp Trizkit

4
Kata kunci var dalam C # berarti membiarkan kompiler menyimpulkan jenis pada waktu kompilasi. Jadi dalam contoh di atas int dan var mendefinisikan variabel tipe yang sama - int. Ini berguna jika Anda memiliki nama jenis yang panjang, atau jika Anda ingin referensi jenis anonim. Ini aneh karena user1618171 telah mencampur dua gaya deklarasi variabel - mungkin salah ketik.
Daniel James Bryars

2

Saya ingin mengubah warna ke tingkat kecerahan tertentu - tidak peduli apa kecerahan warna sebelumnya - inilah fungsi JS sederhana yang tampaknya berfungsi dengan baik, meskipun saya yakin itu bisa lebih pendek

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

Coolio! Saya berasumsi bahwa pmemiliki jangkauan 0-100? Saya bahkan tidak tahu cara mendefinisikan kecerahan dengan benar di RGB, itu hal HSL. Misalnya, apakah #FF00FFlebih terang dari #FF0000? Jika demikian, itu akan menyiratkan bahwa magenta dua kali lebih terang dari merah. Oleh karena itu, tes merah murni digunakan. Lulus merah murni #FF0000, atur kecerahan 50%, dan ini dia #FF4040, benarkah itu? Saya kira akan membuat kecerahan 50% merah, kita akan menjadi lebih gelap, melihat bahwa itu sudah sepenuhnya cerah .. seperti dalam #800000atau kecerahan 150% akan #FF8080. Apakah merah muda merah cerah? atau merah sudah sepenuhnya cerah?
Pimp Trizkit

Anda benar - saya seharusnya menyebutkan bahwa p harus berada dalam kisaran 1-100!
Torbjörn Josefsson

# FF00FF memiliki nilai 255 di saluran merah, 0 di saluran hijau dan 255 di saluran biru. Semakin tinggi nilai gabungan dalam saluran, semakin tinggi kecerahan warna. Angka p menyatakan bahwa kita ingin warna baru menjadi 50% seterang warna aslinya. Saya tidak 100% bahwa # FF4040 adalah jawaban yang benar untuk "50% seterang mungkin Merah". Memproduksi corak yang lebih gelap (dengan, dalam hal ini, nilai yang lebih rendah di saluran merah) akan memerlukan modifikasi
Torbjörn Josefsson

Ya, saya baru saja menunjukkan ambiguitas dalam berbicara tentang kecerahan dalam RGB. Jika dikonversi ke HSL, Lsaluran tersebut benar-benar kecerahan. Masalah [mental pribadi] saya di sini adalah, bagi saya, #FF0000sepenuhnya cerdas. Dan #FF4040lebih Ringan tetapi tidak lebih cerah .... bagi saya lebih ringan berarti lebih dekat ke putih, seperti merah muda. Dan kecerahan adalah seberapa banyak yang didapat, dan penuh merah, begitu merah, penuh terang. Karena itu, #FF0000tidak bisa dibuat lebih cerah .. tapi lebih .. lebih ringan ... mungkin aku hanya orang aneh, lol !! Saya benar-benar tidak tahu teori warna, sooo, saya benar-benar hanya berbicara tentang ...
Pimp Trizkit

Tapi saya tahu bahwa ketika saya mengubah kecerahan monitor saya, The Reds tidak berubah menjadi merah muda ... bagi saya. Jadi ini mungkin di mana saya memulai logika saya.
Pimp Trizkit

1

Metode berikut ini akan memungkinkan Anda untuk meringankan atau menggelapkan nilai eksposur dari string warna Hexadecimal (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");
    }

}

Untuk nilai parameter terakhir di GetHexFromRGB (), Masukkan nilai ganda di antara -1 dan 1 (-1 berwarna hitam, 0 tidak berubah, 1 berwarna putih):

// 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%;

0

Bagaimana warna naungan sederhana dalam 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

Ini adalah versi php dari jawaban Pablo. Sayangnya, ini lebih panjang dan lebih lambat dari solusi akhir dan tidak mencerahkan warna dengan akurat. Itu menggelapkan mereka secara akurat tho. Tes dengan warna merah murni (# FF0000), cahaya 25% seharusnya (# FF4040). Lihatlah akhir jawaban saya untuk versi final Kevin M tentang solusi akhir v2.
Pimp Trizkit

0

Saya membuat port dari pustaka xcolor yang sangat baik untuk menghapus ketergantungan jQuery-nya. Ada banyak fungsi di sana termasuk warna-warna terang dan gelap.

Sungguh, mengubah hex ke RGB adalah fungsi yang sepenuhnya terpisah dari warna-warna cerah atau gelap. Tolong jaga agar tetap KERING. Bagaimanapun, begitu Anda memiliki warna RGB, Anda bisa menambahkan perbedaan antara level cahaya yang Anda inginkan dan level cahaya yang Anda miliki untuk masing-masing nilai 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)
}

Lihat https://github.com/fresheneesz/xolor untuk sumber lebih lanjut.


Saya belum menganalisis kode karena berkaitan dengan OP saya (kecepatan / ukuran / akurasi). Tetapi saat pertama kali membaca ada beberapa komentar yang harus dibuat: 1) Saya setuju bahwa mengubah hex ke RGB dapat dilihat sebagai fungsi yang sepenuhnya terpisah .. JIKA masalah saya dimaksudkan untuk diselesaikan dengan fungsi kering, yang bukan keharusan. Tujuannya di sini adalah untuk memiliki jawaban (lihat Versi 2) yang super cepat dan super kecil (2 baris!) Dan jawaban yang meringankan dan menggelapkan warna hex ... khususnya ... sebagai mandiri yang berdiri sendiri fungsi. Sehingga, dalam penggunaan terakhirnya, itu akan menjadi panggilan fungsi tunggal yang sederhana. <
Cont

2) Dan kasus dengan Versi 3, dengan permintaan populer, adalah niat untuk memiliki fungsi universal mandiri sepenuhnya, secepat dan sekecil mungkin, yang secara membabi buta dapat mengambil warna hex atau RGB dan dalam semua variasi. Oleh karena itu, konversi hex ke RGB diperlukan. <cont.>
Pimp Trizkit

3) Setelah analisis sederhana dari kode. Tampaknya memang akan berjalan lebih lambat dan jelas jauh lebih besar dari Versi 2 saya (yang merupakan jawaban nyata untuk OP saya; versi 3 adalah untuk massa). Agar adil, saya harus membandingkan kode ini dengan RGB Versi 2 saya yang tidak melakukan konversi dan tampaknya menjawab poin Anda tentang kekeringan. Dan sejujurnya, port Anda tidak jauh lebih sederhana untuk dipahami daripada 2 liner saya untuk hex. Jadi, sementara pengeringnya, sebenarnya tidak banyak, jika ada, lebih sederhana. (kekeringan tidak banyak membantu untuk memahami-kemampuan) <lanjutan.>
Pimp Trizkit

4) My RGB Version 2 adalah fungsi tanpa konversi 2 baris jika Anda menginginkannya. Solusi khusus saya untuk OP asli saya ingin hex. Itu sebabnya ada dua jenis Versi 2. Tetapi Anda menyebutkan poin tentang konversi kekeringan dan hex jadi kami sekarang benar-benar fokus pada versi 3. Versi 3 datang jauh kemudian; hanya setelah Versi 2 populer. <cont.>
Pimp Trizkit

5) Sementara saya akan setuju bahwa kekeringan umumnya membantu untuk universalitas. Dan dalam banyak kasus, untuk kemampuan memahami. Sayangnya dengan biaya dalam contoh ini. Biaya ini adalah bahwa ini jauh lebih besar dan tampaknya jauh lebih lambat dan tampaknya menggunakan lebih banyak memori baik pada stack (dengan sifatnya yang rekursif) dan global (2 fungsi; dibandingkan dengan v2).
Pimp Trizkit

0

Saya sudah lama ingin dapat menghasilkan warna / nuansa warna, berikut ini adalah solusi JavaScript saya:

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

Beberapa contoh penggunaan akan membantu. Dan mungkin beberapa penjelasan mengapa versi ini lebih dari yang lain. Versi ini tampaknya berjalan jauh lebih lambat. Dan itu jauh lebih lama. Dan sepertinya tidak teduh secara akurat. Sepertinya Anda menggunakan LERP, atau yang serupa..yang bagus. Sayangnya, ini hanya dari satu saluran, maka nilai yang sama digunakan di semua saluran. Ini tidak benar, untuk mendapatkan akurasi yang lebih tinggi, Anda harus LERP setiap saluran secara individual. Seperti jawaban saya untuk pertanyaan ini. Plus lebih kecil dan lebih cepat dan memeriksa kesalahan dan menangani rgb, dan melakukan konversi, saya bisa melanjutkan
Pimp Trizkit

Contoh penggunaan: varyHue ("6e124c", 77) di mana argumen pertama adalah warna dalam hex dan yang kedua perubahan persentase. Persentase perubahan positif menaungi (menghitamkan) sementara nilai negatif mewarnai (mencerahkan) hasilnya. Saya menulis rutinitas sebagai upaya pertama saya hanya beberapa jam sebelum saya tiba di halaman ini dan mempostingnya hanya sebagai hal yang menarik. Saya tidak sadar bahwa saya harus meningkatkan upaya Anda atau bahwa saya memerlukan persetujuan Anda sebelum melakukannya. Ini sepenuhnya pekerjaan saya sendiri tanpa referensi ke orang lain. Saya belum pernah mendengar LERP saya akan memeriksanya, terima kasih atas sarannya.
user2655360

Hehe, well, tentu saja Anda tidak perlu melakukan apa-apa! Dan kami semua berterima kasih atas upaya Anda! Kekhawatiran utama pertama saya adalah yang tercantum pertama. Mencoba membantu Anda dengan jawaban Anda sehingga dapat memperoleh suara. (perlihatkan penggunaan, dan penjelasan tentang cara kerjanya, dll.) Hal-hal lain jelas merupakan analisis cepat untuk membantu memajukan pengetahuan setiap orang . Maaf, jika sepertinya agak agresif. Tapi saran lain adalah membuatnya menerima #warna hex. Maaf jika sepertinya ... "persetujuan" ... Saya melihatnya sebagai ulasan sejawat. Jika Anda tidak ingin seseorang menganalisis kode Anda, atau menawarkan umpan balik, saya minta maaf.
Pimp Trizkit

0

Pendekatan Anda ok :) Saya menyederhanakan versi terpendek Anda sedikit (untuk kontrol saturasi lihat di sini )

(col,amt)=> (+('0x'+col)+amt*0x010101).toString(16).padStart(6,0)

Dan versi dengan # dan rentang warna memeriksa


0

Saya membuat paket sederhana juga. Saya menggunakan cembung IR ^ 3, tentu saja, nilai-nilai RGB dalam IN ^ 3 yang tidak cembung jadi ini tidak benar-benar sempurna

Untuk menggelapkan saya menggunakan yang berikut ini

for (let i = 0; i < rgb.length; i++) {
   rgb[i] = Math.floor(rgb[i] - ratio * rgb[i]);
}

Dan untuk meringankan

for (let i = 0; i < rgb.length; i++) {
   rgb[i] = Math.ceil(rgb[i] + ratio * (255 - rgb[i]));
}

Ini paketnya https://github.com/MarchWorks/colortone

Demo https://colortone.now.sh/

dengan cara di mana saya melakukan hal-hal jika Anda lulus rasio -1 Anda akan berakhir dengan hitam, Putih jika rasionya 1. Melewati 0 karena rasio tidak akan mengubah warna


0

Saya membutuhkannya di C #, mungkin membantu pengembang .net

public static string LightenDarkenColor(string color, int amount)
    {
        int colorHex = int.Parse(color, System.Globalization.NumberStyles.HexNumber);
        string output = (((colorHex & 0x0000FF) + amount) | ((((colorHex >> 0x8) & 0x00FF) + amount) << 0x8) | (((colorHex >> 0xF) + amount) << 0xF)).ToString("x6");
        return output;
    }

Anda mengonversi fungsi "tidak berfungsi" yang tidak berhubungan dengan angka nol di depan, dan dapat melampaui FF dalam jumlah, = memodifikasi komponen warna di atas ...
B. Pergi

Ketika saya mencoba fungsi itu tidak berfungsi karena nilai-nilai non hex (16 = 0xF) dan (8 = 0x8) dan memberikan warna di 8 posisi, tetapi sekarang berfungsi dengan sangat baik
Nassim

apakah Anda mencoba meningkatkan dari FF? (katakanlah dari 0xFFFFFF + 0x000004): kode Anda bergulir di atas nilai maks (katakanlah ke 0x1000003), alih-alih tidak meningkat, dan terutama mengatur 2 komponen warna atas ke 00 yang merupakan perubahan terbesar yang bisa mereka lakukan ...
B. Pergi

Anda benar, terima kasih atas komentarnya, kecuali input batas sekitar fff dan 000 akan bekerja dengan baik.
Nassim
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.