js变亮/变暗颜色

时间:2013-01-25 21:52:16

标签: javascript jquery colors hex

我正在尝试创建一些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 - 知道这有什么问题吗?

3 个答案:

答案 0 :(得分:2)

无论原始CSS如何,

bgColor都不一定是#RRGBB格式。它可以是以下任何一种:

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

你必须解析每一个。

如果您能够以正确的格式在JavaScript源代码中获得原始颜色,那将会容易得多。

答案 1 :(得分:0)

好吧,我在下面的回答并没有使用JQuery。但无论如何,它应该可以作为JQuery函数使用。正如在他的回答中提到的Niet the Dark Absol,下面的函数可以解析各种类型的颜色代码,除了书面名称(IE。除了单词blue)。不幸的是,这使用Lerp而不是HSL。所以它不是100%准确,但非常接近。对于这种小的不准确性,我们获得了很大的速度和更小的尺寸。

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

function shadeBlendConvert(p, from, to){
    if(!this.sbcRip)this.sbcRip=function(d){
        var l=d.length,RGB=new Object();
        if(l>9){
            d=d.split(",");
            RGB[0]=i(d[0].slice(4)),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
        }else{
            if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:""); //3 digit
            d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=l==9||l==5?r(((d>>24&255)/255)*10000)/10000:-1;
        }
        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=sbcRip(from),t=sbcRip(to);
    if(h)return "rgb("+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+(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)*0x1000000+r((t[0]-f[0])*p+f[0])*0x10000+r((t[1]-f[1])*p+f[1])*0x100+r((t[2]-f[2])*p+f[2])).toString(16).slice(f[3]>-1||t[3]>-1?1:3);
}

其中p是从0100的百分比,fromto分别是起始颜色和结束颜色。

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

  • #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 = shadeBlendConvert(0.3,color1); // rgb(114,93,20) + [30% Lighter] => rgb(156,142,91)
var c3 = shadeBlendConvert(-0.13,"#F3A"); // #F3A + [13% Darker]  => #de2c94

有关更多使用选项,请参阅链接。有很多。

PT

答案 2 :(得分:0)

我遇到了类似的问题,这就是为什么我自己一直在寻找快速解决方案的原因。尽管这些解决方案无法满足我的需求,所以我做到了:

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 <1/255,这是可以保证的)。

负值会使它变暗,但是指数防护措施无法朝那个方向起作用,它们会很快导致灾难性的失败。

(从现在开始,代码尚未经过测试)

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