โปรแกรมทำให้สีจางลงหรือเข้มขึ้นเป็นสี hex (หรือ rgb และสีผสม)


503

นี่คือฟังก์ชั่นที่ผมใช้ในการปรับสีให้สว่างโดยทางโปรแกรมหรือทำให้สีหกเหลี่ยมเข้มขึ้นตามจำนวนที่กำหนด เพียงส่งผ่านสตริงที่ชอบ"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);
}


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

เพื่อการพัฒนาใช้ที่นี่เป็นรุ่นที่อ่านง่ายกว่า:

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

และในที่สุดรุ่นที่จะจัดการกับสีที่อาจ (หรืออาจจะไม่) มี "#" ในตอนแรก การปรับแต่งเพิ่มเติมสำหรับค่าสีที่ไม่เหมาะสม:

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

ฉันเดาคำถามหลักของฉันคือฉันถูกต้องที่นี่? สิ่งนี้ไม่รวมสถานการณ์ (ปกติ) บางสถานการณ์หรือไม่


1
หากคุณไม่ได้ผลลัพธ์ที่คาดหวังเมื่อปรับเปลี่ยนสีฉันขอแนะนำให้ดูในพื้นที่สี LAB ซึ่งใกล้เคียงกับวิสัยทัศน์ของมนุษย์มากขึ้น หลายภาษามีห้องสมุดสำหรับการแปลง จากประสบการณ์ของฉันโดยเฉพาะเฉดสีส้มอาจมีปัญหาเมื่อมืดหรือลดน้ำหนัก
Henrik

จุดที่ดีมาก อย่างไรก็ตามจุดประสงค์หลักของคำถามนี้คือการค้นหาอันดับแรกรันไทม์ที่เร็วที่สุดและสูตรขนาดที่เล็กที่สุด ... และประการที่สองคือความถูกต้อง ดังนั้นทำไมฉันไม่จัดการกับการแปลงเป็น HSL หรืออะไรก็ตาม นี่ความเร็วและขนาดสำคัญกว่ากัน แต่อย่างที่คุณเห็นด้วยสูตรเวอร์ชั่น 2 ของฉัน การใช้ LERP เพื่อแรเงาจะส่งผลให้ส้มสวยงามตลอดช่วงที่ร่ม ลองดูที่แผนภูมิสีด้านล่างและแจ้งให้เราทราบว่าช่วงสีนั้นไม่สวยใกล้เคียงกับความถูกต้องจริงหรือไม่
Pimp Trizkit

ฉันสับสนเล็กน้อยกับโครงสร้างในที่นี่ แต่คุณพูดถูกระดับสีส้มสำหรับเฉดสี Color1 ดูเหมือนจะดีมาก
Henrik

ฮ่า ๆ คุณหมายถึง shadeColor2 ฉันเดาว่าโครงสร้างที่คุณพูดถึงนั้นเป็นเค้าโครงโดยรวมของคำตอบหรือไม่? คำแนะนำใดที่จะทำให้ชัดเจนยิ่งขึ้น?
Pimp Trizkit

3
มีเพียงปัญหาเดียวในฟังก์ชั่นที่มี # ด้านบนคือมันไม่ได้สร้างศูนย์นำถ้ารหัสฐานสิบหกสุดท้ายเริ่มต้นด้วยเลขศูนย์ ตัวอย่างเช่นหากรหัสฐานสิบหกคือ # 00a6b7 จะส่งออกเป็น # a6b7 ซึ่งจะไม่ทำงานหากใช้เป็น css คุณสามารถแก้ไขได้โดยแทนที่บรรทัดส่งคืนโดยสิ่งนี้: var string = "000000" + (g | (b << 8) | (r << 16)) toString (16); ส่งคืน (usePound? "#": "") + string.substr (string.length-6);
Rafael Levy

คำตอบ:


877

คำตอบนี้กลายเป็นสัตว์ร้ายของตัวเอง เวอร์ชั่นใหม่หลายรุ่นมันเริ่มจะงี่เง่า ขอบคุณมากสำหรับผู้มีส่วนร่วมมากมายทุกคนในคำตอบนี้ แต่เพื่อให้ง่ายสำหรับฝูง ผมเก็บไว้ทุกรุ่น / ประวัติศาสตร์ของวิวัฒนาการของคำตอบนี้ไปฉันGitHub และเริ่มต้นใหม่ด้วย Clean บน StackOverflow ที่นี่ด้วยเวอร์ชั่นใหม่ล่าสุด ขอขอบคุณเป็นพิเศษสำหรับMike 'Pomax' Kamermansสำหรับรุ่นนี้ เขาให้คณิตศาสตร์ใหม่แก่ฉัน


ฟังก์ชั่นนี้ ( pSBC) จะใช้สีของเว็บ HEX หรือ RGB pSBCสามารถแรเงาได้เข้มขึ้นหรือจางลงหรือผสมผสานกับสีที่สองและยังสามารถส่งผ่านได้อย่างถูกต้อง แต่แปลงจาก Hex เป็น RGB (Hex2RGB) หรือ RGB เป็น Hex (RGB2Hex) ทั้งหมดโดยที่คุณไม่รู้ด้วยซ้ำว่าคุณกำลังใช้รูปแบบสีอะไร

สิ่งนี้ทำงานได้เร็วมากอาจจะเร็วที่สุดโดยเฉพาะเมื่อพิจารณาถึงคุณสมบัติมากมาย มันเป็นเวลานานในการสร้าง ดูเรื่องราวทั้งหมดของฉันGitHub หากคุณต้องการวิธีที่เล็กที่สุดและเร็วที่สุดในการแรเงาหรือการผสมผสานให้ดูฟังก์ชั่นไมโครด้านล่างและใช้ปีศาจความเร็ว 2 ซับอย่างใดอย่างหนึ่ง มันยอดเยี่ยมสำหรับแอนิเมชั่นที่รุนแรง แต่เวอร์ชั่นนี้เร็วพอสำหรับแอนิเมชั่นส่วนใหญ่

ฟังก์ชั่นนี้ใช้ Log Blending หรือ Linear Blending อย่างไรก็ตามจะไม่แปลงเป็น HSL เพื่อให้สีจางลงหรือเข้มขึ้นอย่างเหมาะสม ดังนั้นผลลัพธ์จากฟังก์ชั่นนี้จะแตกต่างจากฟังก์ชั่นที่ใหญ่กว่าและช้ากว่ามากที่ใช้ HSL

jsFiddle กับ pSBC

github> pSBC Wiki

คุณสมบัติ:

  • ตรวจจับและยอมรับสี Hex มาตรฐานโดยอัตโนมัติในรูปแบบของสตริง ตัวอย่างเช่น: หรือ"#AA6622""#bb551144"
  • ตรวจจับและยอมรับสี RGB มาตรฐานโดยอัตโนมัติในรูปแบบของสตริง ตัวอย่างเช่น: หรือ"rgb(123,45,76)""rgba(45,15,74,0.45)"
  • เฉดสีเป็นสีขาวหรือสีดำตามเปอร์เซ็นต์
  • ผสมสีเข้าด้วยกันเป็นเปอร์เซ็นต์
  • ทำการแปลง Hex2RGB และ RGB2Hex ในเวลาเดียวกันหรือเดี่ยว
  • ยอมรับรหัสสี HEX 3 หลัก (หรือ 4 หลัก w / alpha) ในรูปแบบ #RGB (หรือ #RGBA) มันจะขยายพวกเขา ตัวอย่างเช่น: "#C41"กลายเป็น"#CC4411"กลายเป็น
  • ยอมรับและ (เชิงเส้น) ผสมช่องอัลฟา หากc0สี (จาก) หรือสีc1(ถึง) มีช่องอัลฟาแล้วสีที่ส่งคืนจะมีช่องอัลฟา หากสีทั้งสองมีช่องอัลฟ่าสีที่ส่งคืนจะเป็นการผสมผสานเชิงเส้นของช่องอัลฟาสองช่องทางโดยใช้เปอร์เซ็นต์ที่กำหนด (ราวกับว่าเป็นช่องสีปกติ) หากหนึ่งในสองสีเท่านั้นที่มีช่องอัลฟาอัลฟ่านี้จะถูกส่งผ่านไปยังสีที่ส่งคืน สิ่งนี้ช่วยให้หนึ่งในการผสมผสาน / แรเงาสีโปร่งใสในขณะที่รักษาระดับความโปร่งใส หรือถ้าระดับความโปร่งใสควรผสมผสานเช่นกันตรวจสอบให้แน่ใจว่าทั้งสองสีมีอัลฟ่า เมื่อแรเงามันจะผ่านช่องอัลฟาผ่านตรง หากคุณต้องการการแรเงาขั้นพื้นฐานที่แรเงาช่องอัลฟาก็ให้ใช้rgb(0,0,0,1)หรือrgb(255,255,255,1)เป็นของคุณc1สี (ถึง) สี (หรือเลขฐานสิบหกเทียบเท่า) สำหรับสี RGB ช่องอัลฟาของสีที่ส่งคืนจะถูกปัดเศษเป็นทศนิยม 3 ตำแหน่ง
  • การแปลง RGB2Hex และ Hex2RGB นั้นมีความหมายโดยนัยเมื่อใช้การผสม โดยไม่คำนึงถึงc0สี (จาก) สีที่ส่งคืนจะอยู่ในรูปแบบสีของสีc1(ถึง) เสมอหากมีอยู่ หากไม่มีc1สี (ไป) ให้ผ่าน'c'เป็นc1สีและมันจะแรเงาและแปลงสิ่งที่เป็นc0สี หากต้องการการแปลงเท่านั้นให้ส่งผ่าน0เป็นเปอร์เซ็นต์ ( p) เช่นกัน หากไม่ใส่c1สีหรือไม่ใส่สีstringก็จะไม่ถูกแปลง
  • มีการเพิ่มฟังก์ชั่นรองลงในโกลบอลเช่นกัน pSBCrสามารถส่งผ่านสี Hex หรือ RGB และส่งคืนวัตถุที่มีข้อมูลสีนี้ มันอยู่ในรูปแบบ: {r: XXX, g: XXX, b: XXX, a: X.XXX} ที่ไหน.r, .gและ.bมีช่วง 0 ถึง 255 และเมื่อไม่มีอัลฟา: .a-1 มิฉะนั้น: .aมีช่วง 0.000 ถึง 1.000
  • สำหรับการส่งออก RGB มันจะออกผลลัพธ์rgba()มากกว่าrgb()เมื่อสีที่มีช่องอัลฟาที่ถูกส่งผ่านเข้าc0(จาก) และ / หรือc1(เพื่อ)
  • เพิ่มการตรวจสอบข้อผิดพลาดเล็กน้อยแล้ว มันไม่สมบูรณ์แบบ มันยังสามารถพังหรือสร้างการพูดปด แต่มันจะจับบางสิ่ง nullโดยทั่วไปถ้าโครงสร้างที่ไม่ถูกต้องในบางวิธีหรือถ้าเปอร์เซ็นต์ไม่ได้เป็นจำนวนหรือออกจากขอบเขตก็จะกลับ ตัวอย่าง: pSBC(0.5,"salt") == nullที่ซึ่งคิดว่า#saltเป็นสีที่ถูกต้อง ลบสี่บรรทัดที่ลงท้ายด้วยreturn null;เพื่อลบคุณลักษณะนี้และทำให้เร็วขึ้นและเล็กลง
  • ใช้ Log Blending ส่งผ่านtrueสำหรับl(พารามิเตอร์ที่ 4) เพื่อใช้การผสมเชิงเส้น

รหัส:

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

การใช้งาน:

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

ภาพด้านล่างจะช่วยแสดงความแตกต่างในวิธีการผสมสองวิธี:


ฟังก์ชั่นไมโคร

ถ้าคุณต้องการความเร็วและขนาดจริง ๆ คุณจะต้องใช้ RGB ไม่ใช่ HEX RGB นั้นตรงไปตรงมาและเรียบง่ายกว่า HEX เขียนช้าเกินไปและมีหลายรสเกินไปสำหรับสองซับง่ายๆ (IE ซึ่งอาจเป็นรหัส HEX 3, 4, 6 หรือ 8 หลัก) คุณจะต้องเสียสละคุณสมบัติบางอย่างไม่มีการตรวจสอบข้อผิดพลาดไม่มี HEX2RGB หรือ RGB2HEX เช่นกันคุณจะต้องเลือกฟังก์ชั่นเฉพาะ (ตามชื่อฟังก์ชั่นด้านล่าง) สำหรับคณิตศาสตร์การผสมสีและถ้าคุณต้องการแรเงาหรือการผสม ฟังก์ชั่นเหล่านี้รองรับช่องอัลฟ่า และเมื่อสีอินพุตทั้งสองมีอัลฟาก็จะเป็น Linear Blend หากมีเพียงหนึ่งในสองสีเท่านั้นที่มีอัลฟามันจะผ่านไปยังสีที่เกิดขึ้น ด้านล่างนี้เป็นฟังก์ชั่นซับสองด้านที่รวดเร็วและเล็กอย่างไม่น่าเชื่อ:

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

ต้องการข้อมูลเพิ่มเติมหรือไม่ อ่านเขียนขึ้นเต็มบนGitHub

PT

(สดุดีถ้าใครมีคณิตศาสตร์สำหรับวิธีการผสมแบบอื่นกรุณาแชร์)


8
รุ่น PHP สำหรับผู้ที่ต้องการ: gist.github.com/chaoszcat/5325115#file-gistfile1-php
ไลโอเนลชาน

28
ฉันใช้TinyColor -tinycolor.darken(color,amount);
FWrnr

4
โพสต์ที่ยอดเยี่ยม ... :) ... เพิ่งสร้างส่วนขยายของ Swift: gist.github.com/matejukmar/1da47f7a950d1ba68a95
Matej Ukmar

2
นี่คือเวอร์ชั่น PHP สำหรับเวอร์ชั่น shadeColor2 ที่ได้รับการอัพเดต: 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
ขออภัยฉันพลาดจุดนั้นไปแล้ว อาจมีสองเหตุผล อย่างแรกและชัดเจนคือฉันใช้ Math.Round และคุณไม่ต้องใช้เลขทศนิยมสำหรับการระบายสีที่แม่นยำ (สีไม่มีทศนิยมในฐานสิบหก) ตัวอย่างเช่นถ้าช่องสีแดงเป็น 8เพิ่ม10%คุณจะได้รับซึ่งรอบ8.8 9จากนั้นนำ9.09%ออกไปจากและคุณได้รับ9 8.1819รอบไหน8เป็นตัวอย่างที่ไม่ดี แต่ก็ยังแสดงให้เห็นว่าคุณจะได้รับ9.09%ของและไม่ได้9 8.8ดังนั้นอาจมีตัวเลขอยู่ในนั้นซึ่งไม่ได้ปัดกลับอย่างเดียวกับตัวอย่างของฉันที่นี่
Pimp Trizkit

121

ฉันทำโซลูชันที่ใช้งานได้ดีมากสำหรับฉัน:

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

4
ดีฉันชอบเปอร์เซ็นต์! 1 Tho ผมจะอาจจะทำR = ((R<255)?R:255).toString(16);แล้วR = R.length==1 ? "0"+R : Rสำหรับความเร็ว และฉันไม่แน่ใจว่าจุดของ toUpperCase?
Pimp Trizkit

มันไม่จำเป็น ฉันเพิ่มเฉพาะสำหรับพิมพ์สวยในขณะทดสอบ ฉันจะแก้ไขมัน
Pablo

ดีมาก. อย่างไรก็ตามควรเบากว่า 100% ไม่ให้กลายเป็นสีขาวเต็มและมืด 100% เสมอดำไม่ว่าสีอะไร ดูเหมือนว่า -100 จะทำให้สีใด ๆ สีดำ แต่ 100 (บวก) ไม่ทำให้ขาวอย่างสมบูรณ์
Kevin M

4
ไม่สามารถใช้งานกับสีทึบเช่น # ff0000, # 00ff00, # 0000ff
Hitori

เพื่อให้ใช้งานได้กับสีดำฉันเพิ่งแฮ็คนี้ 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

นี่คือหนึ่งซับง่ายสุดตามคำตอบของ 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));
}

ตัวอย่าง:

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

7
"ง่ายสุด"
Andrew

5

นี่คือสิ่งที่ฉันใช้ตามฟังก์ชั่นของคุณ ฉันชอบที่จะใช้ขั้นตอนมากกว่าเปอร์เซ็นต์เพราะมันใช้งานง่ายกว่าสำหรับฉัน

ตัวอย่างเช่นค่า 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;

}

พบว่ามีประโยชน์มากกว่าคำตอบยอดนิยมเพราะคำตอบยอดนิยมทำให้สีของฉันเข้มขึ้นแทนที่จะเข้มกว่า ไชโยเอริค
Worm

4

ฉันลองใช้ฟังก์ชันของคุณและมีข้อบกพร่องเล็กน้อย: หากค่า '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;

อาจจะไม่ดีนัก แต่ใช้งานได้ ฟังก์ชั่นที่ยอดเยี่ยม BTW สิ่งที่ฉันต้องการ :)


1
ขอบคุณสำหรับการแก้ไขข้อบกพร่องและคำชม! น่าเสียดายที่มันไม่ใช่คำตอบว่ามีวิธีที่เร็วกว่าหรือไม่ซึ่งเป็นคำถามหลักของฉัน เช่นเดียวกับที่ใช้เลขฐานสิบหกทั้งหมดและไม่มีการแปลงฐาน ฉันคิดว่าคุณบอกฉันว่าฉันมีรหัสที่ถูกต้อง (+1) น่าเสียดายที่การแก้ไขเพิ่มค่าใช้จ่ายมากขึ้น (ตอนนี้คุณโทรไปที่สาย 6 ครั้ง) และจูบน้อยลงเล็กน้อย อาจจะเร็วกว่าเพื่อตรวจสอบว่าหมายเลข base10 คือ 15 หรือน้อยกว่าก่อนการแปลง base16 แต่ฉันชอบ!
Pimp Trizkit

4

คุณคิดเกี่ยวกับการแปลง rgb> hsl หรือไม่ จากนั้นเพียงแค่ย้ายความส่องสว่างขึ้นและลง? นั่นคือวิธีที่ฉันจะไป

ดูอัลกอริทึมบางอย่างทำให้ฉันมีเว็บไซต์ต่อไปนี้

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จาวาสคริปต์

แก้ไขลิงค์ด้านบนไม่สามารถใช้งานได้อีกต่อไป คุณสามารถดู 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. คุณมีฟังก์ชั่นและhslToRgbrgbToHsl
  2. พารามิเตอร์colorValueเป็นสตริงในรูปแบบ#RRGGBB

แม้ว่าเราจะพูดถึง CSS มีไวยากรณ์สำหรับการระบุhsl / hslaสำหรับ IE9 / Chrome / Firefox


ที่น่าสนใจ แต่ฉันจะไม่ต้องแปลงจากสตริงฐานสิบหกเป็น rgb เป็น hsl หรือไม่ ดูเหมือนว่ามันซับซ้อนกว่า บางทีฉันอาจจะพลาดอะไรซักอย่าง แต่ฉันกำลังมองหาวิธี KISS ที่จะทำได้เร็วที่สุดเท่าที่จะทำได้ (เวลาดำเนินการ) ฉันรู้สึกว่าถ้าฉันสามารถทำทั้งหมดใน hex ที่จะเร็วที่สุด แต่โซลูชันที่ฉันพัฒนาที่นี่เกี่ยวข้องกับการไป rgb เพื่อให้สามารถเพิ่มจำนวนที่เพิ่มขึ้น
Pimp Trizkit

ใช่ฉันคิดว่ามันจะช้ากว่าซับซ้อนกว่าและหากคุณไม่ได้ใช้การแปลง rgb เป็น hsl ที่อื่นก็อาจจะไม่ใช่วิธีที่ง่ายที่สุด อย่างไรก็ตามจะมีความแม่นยำมากกว่าการเพิ่มค่า rgb แม้ว่าฉันจะไม่ค่อยเป็นคนสี ทุกอย่างขึ้นอยู่กับว่าคุณต้องการเดาว่าถูกต้องแค่ไหน
James Khoury

การสูญเสียความแม่นยำที่คุณพูดถึงคืออะไร? ฉันคิดว่าคุณหมายถึง [เว็บ] ทุกสีไม่สามารถเข้าถึงด้วย rgb หรืออะไรบางอย่าง?
Pimp Trizkit

อย่างที่ฉันบอกว่าฉันไม่ค่อยรู้เรื่องสีมากนัก: ทฤษฎีสีวิกิ
James Khoury

@Pimp Trizkit: มันแม่นยำน้อยกว่าเพราะ (และนี่เป็นเพียงทฤษฎีของฉัน ... ฉันไม่ใช่ผู้เชี่ยวชาญด้านสี) คุณเปลี่ยนแต่ละช่องในปริมาณเท่ากันไม่ว่าจะเริ่มด้วยสีใด ฉันคิดว่านั่นจะส่งผลให้ความอิ่มตัวลดลงเพราะคุณกำลังนำช่องให้ใกล้ชิดกันมากขึ้น (เป็นเปอร์เซ็นต์) แน่นอนถ้าคุณล้น / อันเดอร์อันนั้นก็ไม่สามารถหลีกเลี่ยงได้
Matthew Crumley

2

รุ่น 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);
    }

5
ไม่เคยใช้ C # มาก่อน แต่ดูเหมือนว่าการประกาศตัวแปรสามรายการสุดท้ายนั้นแปลกกว่า หนึ่งintและสองvarsสำหรับข้อมูลประเภทเดียวกัน
Pimp Trizkit

4
คำหลัก var ใน C # หมายถึงให้คอมไพเลอร์อนุมานชนิดขณะรวบรวม ดังนั้นในตัวอย่างข้างบน int และ var กำหนดตัวแปรชนิดเดียวกัน - int สิ่งนี้มีประโยชน์หากคุณมีชื่อประเภทยาวหรือถ้าคุณต้องการอ้างอิงประเภทที่ไม่ระบุชื่อ มันแปลกเพราะ user1618171 ผสมสองรูปแบบการประกาศตัวแปร - อาจเป็นตัวพิมพ์ผิด
Daniel James Bryars

2

ฉันต้องการเปลี่ยนสีเป็นระดับความสว่างเฉพาะ - ไม่ว่าความสว่างของสีจะมาก่อน - นี่คือฟังก์ชั่น 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;}

Coolio! ฉันคิดว่าpมีช่วง0-100หรือไม่ ฉันไม่รู้ด้วยซ้ำว่าจะกำหนดความสว่างใน RGB ได้อย่างไรนั่นคือสิ่งที่ HSL ตัวอย่างเช่น#FF00FFสว่างกว่า#FF0000? ถ้าเป็นเช่นนั้นนั่นแปลว่าสีม่วงแดงนั้นสว่างเป็นสองเท่าของสีแดง ดังนั้นจึงใช้การทดสอบสีแดงบริสุทธิ์ ผ่านสีแดงบริสุทธิ์#FF0000ตั้งค่าความสว่าง 50% แล้วเราจะได้รับ#FF4040ใช่ไหม ฉันจะคาดเดาของสีแดงเพื่อให้ความสว่าง 50% เราจะได้รับเข้มเห็นว่าแล้วสดใสอย่างเต็มที่ .. เช่นเดียวกับใน#800000หรือ 150% #FF8080ความสว่างจะเป็น สีชมพูแดงสดหรือไม่? หรือสีแดงสว่างเต็มที่อยู่แล้ว
Pimp Trizkit

คุณพูดถูก - ฉันควรจะพูดว่า p ต้องอยู่ในช่วง 1-100!
Torbjörn Josefsson

# FF00FF มีค่า 255 ในช่องสีแดง, 0 ในช่องสีเขียวและ 255 ในช่องสีฟ้า ยิ่งค่าที่รวมกันในแชแนลสูงเท่าใดความสว่างของสีก็จะยิ่งสูงขึ้น ตัวเลข p ระบุว่าเราต้องการให้สีใหม่มีความสว่าง 50% เท่ากับสีดั้งเดิม ฉันไม่ใช่ 100% ที่ # FF4040 เป็นคำตอบที่ถูกต้องสำหรับ "50% ที่สว่างที่สุดเท่าที่เป็นไปได้สีแดง" การผลิตเฉดสีเข้ม (ด้วยในกรณีนี้ค่าที่ต่ำกว่าในช่องสีแดง) จะต้องมีการปรับเปลี่ยน
Torbjörn Josefsson

ใช่ฉันแค่ชี้ให้เห็นความกำกวมในการพูดคุยเกี่ยวกับความสว่างใน RGB หากแปลงเป็น HSL Lช่องนั้นจะสว่างอย่างแท้จริง ปัญหาส่วนตัวของฉันที่นี่สำหรับฉันนั้น#FF0000สดใสอย่างสมบูรณ์ และ#FF4040ก็เบากว่า แต่ไม่สว่างกว่า .... สำหรับฉันเบากว่าหมายถึงขาวมากขึ้นเช่นเดียวกับสีชมพู และความสว่างคือค่าที่ได้รับและสีแดงเต็มรูปแบบดังนั้นสีแดงจึงสว่างเต็มที่ ดังนั้น#FF0000ไม่สามารถทำให้สว่างขึ้น .. แต่ค่อนข้าง .. เบากว่า ... บางทีฉันอาจเป็นแค่คนประหลาด lol !! ฉันไม่รู้ทฤษฎีสีจริง ๆ เลยฉันแค่พูดออกมา ...
Pimp Trizkit

แต่ฉันรู้ว่าเมื่อฉันเปลี่ยนความสว่างบนหน้าจอของฉันสีแดงไม่เปลี่ยนเป็นสีชมพู ... สำหรับฉัน ดังนั้นนี่อาจเป็นที่ที่ฉันเริ่มต้นตรรกะของฉัน
Pimp Trizkit

1

วิธีการต่อไปนี้จะช่วยให้คุณปรับความสว่างหรือความเข้มของค่าแสงของสตริงสีฐานสิบหก (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%;

0

วิธีเงาสีใน 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

นี่เป็นคำตอบของ Pablo เวอร์ชัน php น่าเสียดายที่มันยาวกว่าและช้ากว่าสารละลายสุดท้ายและไม่ทำให้สีจางลงอย่างแม่นยำ มันทำให้พวกมันมืดลงอย่างแม่นยำ ทดสอบด้วยสีแดงบริสุทธิ์ (# FF0000) ควรจางลง 25% (# FF4040) ตรวจสอบคำตอบสุดท้ายของฉันสำหรับคำตอบสุดท้ายของ v2 ในเวอร์ชัน PHP ของ Kevin M
Pimp Trizkit

0

ฉันสร้างพอร์ตของไลบรารี xcolor ที่ยอดเยี่ยมเพื่อลบการพึ่งพา jQuery มีฟังก์ชั่นมากมายในนั้นรวมถึงสีที่เพิ่มความสว่างและความมืด

จริงๆแล้วการแปลงฐานสิบหกเป็น 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เพื่อดูแหล่งที่มาเพิ่มเติม


ฉันยังไม่ได้วิเคราะห์รหัสตามที่เกี่ยวข้องกับ OP ของฉัน (ความเร็ว / ขนาด / ความแม่นยำ) แต่ในตอนแรกอ่านมีความคิดเห็นบางอย่างที่จะทำ: 1) ฉันยอมรับว่าการแปลงฐานสิบหกเป็น RGB สามารถเห็นได้ว่าเป็นฟังก์ชั่นที่แยกจากกันอย่างสมบูรณ์ .. ถ้าปัญหาของฉันตั้งใจที่จะแก้ไขด้วยฟังก์ชั่นแบบแห้ง ความตั้งใจที่นี่คือการได้คำตอบ (ดูรุ่นของฉัน 2) ที่เร็วสุดและเล็กมาก (2 บรรทัด!) และอีกหนึ่งที่สว่างขึ้นและมืดลงเป็นสี hex ... โดยเฉพาะ ... เป็นแบบสแตนด์อโลน ฟังก์ชัน ดังนั้นในการใช้งานครั้งสุดท้ายมันจะเป็นการเรียกใช้ฟังก์ชั่นเดี่ยวอย่างง่าย <cont.>
Pimp Trizkit

2) และกรณีที่มีเวอร์ชัน 3 ตามความต้องการที่ได้รับความนิยมคือความตั้งใจที่จะมีฟังก์ชั่นสากลแบบแยกตัวเองแบบสแตนด์อโลนที่รวดเร็วและเล็กที่สุดเท่าที่จะเป็นไปได้ รูปแบบ ดังนั้นจำเป็นต้องแปลงฐานสิบหกเป็น RGB <ต่อเนื่อง>
Pimp Trizkit

3) เมื่อทำการวิเคราะห์รหัสอย่างง่าย ดูเหมือนว่ามันจะทำงานช้าลงและเห็นได้ชัดว่าใหญ่กว่ารุ่น 2 ของฉัน (ซึ่งเป็นคำตอบที่แท้จริงสำหรับ OP ของฉันเวอร์ชัน 3 สำหรับมวลชน) เพื่อความเป็นธรรมฉันควรเปรียบเทียบรหัสนี้กับรุ่น RGB ของฉันซึ่งไม่ได้ทำการแปลงและดูเหมือนจะตอบจุดของคุณเกี่ยวกับความแห้งแล้ง และพูดตามความเป็นจริงพอร์ตของคุณไม่เข้าใจง่ายกว่าซับ 2 ของฉันสำหรับเลขฐานสิบหก ดังนั้นในขณะที่เครื่องอบแห้งมันก็ไม่มากจริง ๆ ถ้าง่ายกว่า (ความแห้งกร้านไม่ได้ช่วยอะไรมากสำหรับความเข้าใจ)
Pimp Trizkit

4) My RGB Version 2 เป็นฟังก์ชั่นไม่แปลง 2 บรรทัดหากคุณต้องการ โซลูชันเฉพาะสำหรับ OP ต้นฉบับของฉันต้องการเลขฐานสิบหก นั่นเป็นเหตุผลว่าทำไมมีเวอร์ชัน 2 แตกต่างกันสองประเภท แต่คุณพูดถึงประเด็นเกี่ยวกับความแห้งและการแปลงเลขฐานสิบหกดังนั้นตอนนี้เราจึงมุ่งเน้นไปที่เวอร์ชัน 3 เวอร์ชัน 3 มามากในภายหลัง หลังจากเวอร์ชั่น 2 ได้รับความนิยม <ต่อเนื่อง>
Pimp Trizkit

5) ในขณะที่ฉันจะยอมรับว่าความแห้งกร้านมักจะช่วยให้เป็นสากล และในกรณีส่วนใหญ่สำหรับความสามารถในการเข้าใจ น่าเสียดายที่ค่าใช้จ่ายในตัวอย่างนี้ ค่าใช้จ่ายเหล่านี้คือว่ามันใหญ่กว่าและช้ากว่ามากและดูเหมือนว่าจะใช้หน่วยความจำมากขึ้นทั้งในสแต็ก (ด้วยลักษณะที่เรียกซ้ำได้) และในระดับโลก (2 ฟังก์ชั่น; เทียบกับ v2)
Pimp Trizkit

0

ฉันอยากจะผลิตสีอ่อน / เฉดสีมานานแล้วนี่คือโซลูชัน 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);
    }
};

ตัวอย่างการใช้งานบางอย่างจะช่วย และอาจจะมีคำอธิบายว่าทำไมรุ่นนี้เหนือคนอื่นบ้าง รุ่นนี้ดูเหมือนจะทำงานช้าลงอย่างมาก และมันยาวกว่ามาก และดูเหมือนว่าจะไม่ถูกต้อง ดูเหมือนว่าคุณกำลังใช้ LERP หรืออะไรทำนองนี้ที่ดี น่าเสียดายที่มันมาจากช่องเดียวเท่านั้นดังนั้นจึงใช้ค่าเดียวกันในทุกช่อง สิ่งนี้ไม่ถูกต้องเพื่อให้ได้ความแม่นยำสูงขึ้นคุณควร LERP แต่ละช่องแยกกัน อย่างที่ฉันตอบคำถามนี้ บวกกับขนาดที่เล็กกว่าและเร็วกว่าและตรวจสอบข้อผิดพลาดและจัดการ rgb และทำการแปลงฉันสามารถดำเนินการต่อได้
Pimp Trizkit

ตัวอย่างการใช้งาน: varyHue ("6e124c", 77) โดยที่อาร์กิวเมนต์แรกคือสีในฐานสิบหกและเปอร์เซ็นต์การเปลี่ยนแปลงที่สอง เปอร์เซ็นต์การเปลี่ยนแปลงในเชิงบวกที่แรเงา (มืด) ในขณะที่ค่าลบสีอ่อน (จาง) ผล ฉันเขียนกิจวัตรประจำวันเป็นความพยายามครั้งแรกของฉันเพียงไม่กี่ชั่วโมงก่อนที่ฉันจะมาที่หน้านี้และโพสต์ลงบนเรื่องที่น่าสนใจ ฉันไม่ทราบว่าฉันต้องพยายามให้ดีขึ้นหรือต้องการการอนุมัติจากคุณก่อนที่จะทำเช่นนั้น มันเป็นงานของฉันเองโดยไม่มีการอ้างอิงถึงใครเลย ฉันไม่เคยได้ยินของ LERP ฉันจะตรวจสอบขอบคุณสำหรับคำแนะนำ
2655360

เฮ้แน่นอนคุณไม่ต้องทำอะไร! และเราทุกคนขอบคุณสำหรับความพยายามของคุณ! ข้อกังวลหลักแรกของฉันคือสิ่งที่ระบุไว้ก่อน พยายามช่วยคุณด้วยคำตอบเพื่อที่จะได้รับคะแนนโหวต (แสดงประเพณีและคำอธิบายวิธีการใช้งาน ฯลฯ ) สิ่งอื่น ๆ ก็คือการวิเคราะห์อย่างรวดเร็วเพื่อช่วยให้ความรู้ของทุกคนต่อไป ขออภัยถ้ามันดูค่อนข้างก้าวร้าว แต่ข้อเสนอแนะอีกประการหนึ่งคือการทำให้ยอมรับ#สีฐานสิบหก ขออภัยถ้ามันดูเหมือน .. "การอนุมัติ" ... ฉันเห็นว่าเป็นรีวิวแบบเพื่อน หากคุณไม่ต้องการให้ใครบางคนวิเคราะห์รหัสของคุณหรือให้ข้อเสนอแนะฉันขอโทษ
Pimp Trizkit

0

วิธีการของคุณก็โอเค :) ฉันทำให้เวอร์ชันย่อของคุณสั้นลงเล็กน้อย (สำหรับการควบคุมความอิ่มตัวดูที่นี่ )

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

และรุ่นที่มีการตรวจสอบ # และช่วงสี


0

ฉันทำแพ็คเกจง่าย ๆ ด้วย ฉันใช้ความนูนของ IR ^ 3 แน่นอนค่า RGB อยู่ใน IN ^ 3 ซึ่งไม่ได้นูนดังนั้นนี่จึงไม่สมบูรณ์แบบจริงๆ

เพื่อมืดฉันใช้ดังต่อไปนี้

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

และเพื่อให้จางลง

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

นี่คือแพคเกจ https://github.com/MarchWorks/colortone

การสาธิต https://colortone.now.sh/

ด้วยวิธีที่ฉันกำลังทำสิ่งต่าง ๆ ถ้าคุณผ่านอัตราส่วน -1 คุณจะได้สีดำและสีขาวถ้าอัตราส่วนคือ 1 ผ่าน 0 เนื่องจากอัตราส่วนจะไม่เปลี่ยนสี


0

ฉันต้องการมันใน C # อาจช่วยนักพัฒนา. 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;
    }

คุณแปลงฟังก์ชัน "ไม่ทำงาน" ที่ไม่ได้จัดการกับศูนย์นำหน้าและสามารถไปที่ FF ในผลรวม = แก้ไของค์ประกอบสีด้านบน ...
B. ไป

เมื่อฉันลองใช้ฟังก์ชั่นมันไม่ได้ผลเพราะไม่ใช่ค่าเลขฐานสิบหก (16 = 0xF) และ (8 = 0x8) และให้สีในตำแหน่งที่ 8 แต่ตอนนี้มันใช้งานได้ดีมาก
Nassim

คุณลองเพิ่มจาก FF หรือไม่ (พูดจาก 0xFFFFFF + 0x000004): โค้ดของคุณมีมูลค่ามากกว่านั้น (พูดกับ 0x1000003) แทนที่จะไม่เพิ่มขึ้นและโดยเฉพาะอย่างยิ่งการตั้งค่าองค์ประกอบสี 2 ส่วนบนเป็น 00 ซึ่งเป็นการเปลี่ยนแปลงที่ใหญ่ที่สุดที่พวกเขาสามารถทำได้ ...
B ไป

คุณพูดถูกต้องขอบคุณสำหรับคำพูดยกเว้นอินพุตของขอบเขต จำกัด fff และ 000 มันจะทำงานได้ดี
Nassim
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.