【问题标题】:js lighten / darken colorjs 使颜色变亮/变暗
【发布时间】:2013-01-09 22:56:47
【问题描述】:

我正在尝试创建一些 jQuery 函数,将对象 bgcolor 更改为更亮或更暗(您将参数设置为色调的差异)。而且我认为它应该可以工作,但它会破裂。

$.fn.changeBg = function(difference){




    var hexToRgb = function(hex) {
        var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : null;
    }

    var rgbToHex = function(r, g, b) {
        return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
    }

    //returns color n-tones lighter or darker (for negavitve values) from given.
    var changeColor = function(hex,tones){
        var rgb = hexToRgb(hex);
        rgb.r+=tones;
        rgb.g+=tones;
        rgb.b+=tones;

        rgb.r=rgb.r>255?255:rgb.r;
        rgb.r=rgb.r<0?0:rgb.r;

        rgb.g=rgb.g>255?255:rgb.g;
        rgb.g=rgb.g<0?0:rgb.g;

        rgb.b=rgb.b>255?255:rgb.b;
        rgb.b=rgb.b<0?0:rgb.b;

        var hex = rgbToHex( rgb.r , rgb.g , rgb.b );
        return hex;
    }

    var bgColor = $(this).css('background-color');
    var secColor = changeColor(bgColor,difference);
    $(this).css('background-color',secColor);

}

Fiddle - 知道这有什么问题吗?

【问题讨论】:

  • javascript 控制台有答案 ;) 您可能想在调用 .exec() 之后添加 console.log(hex, result);
  • 善待使用它的人,并选择一个有专用通道用于亮度、HSV、HSL、HSB 等的色彩空间。

标签: javascript jquery colors hex


【解决方案1】:

bgColor 不一定是#RRGBB 格式,无论原始 CSS 是什么。它可以是以下任何一种:

  • #RRGGBB
  • #RGB
  • rgb(R, G, B)
  • rgba(R, G, B, A)
  • 姓名

你必须解析它们中的每一个。

如果您可以在 JavaScript 源代码中以正确的格式保存原始颜色,那就容易多了。

【讨论】:

    【解决方案2】:

    好吧,我在下面的回答没有使用 JQuery。但无论哪种方式,它都应该可以作为 JQuery 函数正常工作。正如Niet the Dark Absol在他的回答中提到的那样,下面的函数可以解析各种类型的颜色代码,除了写的名字(IE。除了单词blue)。不幸的是,这使用了线性插值和/或对数插值,而不是 HSL。所以它不是 100% 准确,但非常接近。对于这个小的误差,我们获得了很大的速度和更小的尺寸。

    Programmatically Lighten or Darken a hex color (or rgb, and blend colors)

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

    其中p 是从-1.01.0 的浮点百分比,fromto 分别是起始颜色和结束颜色。而l 默认为false,即对数插值,如果您希望线性插值将true 传递为l

    此功能可以使这些格式的颜色变亮、变暗、混合和转换:

    • #RGB
    • #RRGGBB
    • #RGBA
    • #RRGGBBAA
    • rgb(R,G,B)
    • rgb(R,G,B,A)

    Hex2RGB/RGB2Hex 转换是隐式的。 检查链接以获取更多信息以及此功能的其他版本。主要版本有一些错误检查。也有没有 Hex2RGB/RGB2Hex 转换的版本;它们有点小。

    要按照我认为您想要的方式使用它,请执行以下操作:

    var color1 = "rgb(114,93,20)";
    var c2 = pSBC(0.3,color1); // rgb(114,93,20) + [30% Lighter] => rgb(156,142,91)
    var c3 = pSBC(-0.13,"#F3A"); // #F3A + [13% Darker]  => #de2c94
    

    查看链接了解更多使用选项。有很多。

    PT

    【讨论】:

      【解决方案3】:

      我遇到了类似的问题,这就是我自己寻找快速解决方案的原因。尽管这些解决方案不能满足我的需求,所以我这样做了:

      const lighten = (color, lighten)=>{
        const c = color.replace("#", "");
        let rgb = [parseInt(c.substr(0, 2), 16), parseInt(c.substr(2, 2), 16), parseInt(c.substr(4, 2), 16)];
        let returnstatement = "#";
        rgb.forEach((color)=>{returnstatement+=Math.round(((255-color)*(1-Math.pow(Math.E, -lighten))+color)).toString(16)});
        return returnstatement;
      }
      

      它需要一个十六进制颜色代码和一个亮度参数。由于负指数项,颜色不能超过#ffffff,但足够高的值会让你到达那里(其中 e^-lighten

      负值会导致它变暗,但指数保护在那个方向上不起作用,它们会很快导致灾难性的失败。

      (从这里开始,代码尚未测试)

      const darken = (color, darken)=>{
            const c = color.replace("#", "");
            let rgb = [parseInt(c.substr(0, 2), 16), parseInt(c.substr(2, 2), 16), parseInt(c.substr(4, 2), 16)];
            let returnstatement = "#";
            rgb.forEach((color)=>{returnstatement+=Math.round(color/(1-Math.pow(Math.E, -darken))).toString(16)});
            return returnstatement;
          }
      

      如果你像这样组合它们

      const lightdark = (color, lparam)=>{
       if(lparam>0){
      return lighten(color, lparam);
      }
      return darken(color, lparam);
      }
      

      您将避免双向的指数级灾难

      最后,关于颜色,如果你已经得到 rgb,你可能想检查颜色数据是否在一个数组中,在这种情况下你可以

      const parseColor = (color) => {
        let rgb;
        if (!Array.isArray(color)){
          if(color.includes("#")||color.includes("0x")){
            const c = color.replace("#", "").replace("0x", "");
            rgb = [parseInt(c.substr(0, 2), 16), parseInt(c.substr(2, 2), 16), parseInt(c.substr(4, 2), 16)];
          }else{
            rgb=color.split(",").map((item)=>parseInt(item.trim()));
          }
        }
        return rgb;
      }
      

      当然,这段代码总体上可以提高效率。如果您想捕捉它作为对象到达的可能性,例如

      color={r:0, b:0, g:0}
      

      无论颜色对象的键名如何,

      const rgb = Object.keys(color).map((key)=>color[key])
      

      应该使这种情况正确,(只需将其插入解析器中)因为我还没有听说任何 html 颜色被编码为 cym

      【讨论】:

        猜你喜欢
        • 2013-08-18
        • 2020-06-09
        • 2020-04-04
        • 2016-10-12
        • 1970-01-01
        • 2017-12-27
        • 2012-10-05
        • 1970-01-01
        • 2018-12-23
        相关资源
        最近更新 更多