当前位置: 首页 > Web前端 > CSS

在CSS中使用JavaScript控制颜色

时间:2023-03-30 19:29:09 CSS

背景知识:颜色模型点开这篇文章,你一定想学习如何控制颜色——具体操作我们后面再说。但首先,我们需要对CSS如何标记颜色有一个基本的了解。CSS使用两种颜色模型:RGB和HSL,我们先来简单了解一下。RGBRGB是“红、绿、蓝”的缩写。该模型由三个数字组成,每个数字表示它所代表的颜色在结果颜色中的亮度。在CSS中,每个值的范围是0-255,三个值之间用逗号隔开,作为CSSrgb函数的参数,例如:rgb(50,100,0)。RGB是一种“增量”颜色系统。这意味着每个数字越高,得到的颜色就越亮。如果所有值都相等,则产生灰度颜色;如果所有值都为零,则结果为黑色;如果所有值都是255,则结果为白色。或者,您可以对RGB颜色使用十六进制表示法,其中每种颜色的值从基数10转换为基数16。例如,rgb(50,100,0)在十六进制中写为#326400。虽然我个人更喜欢使用RGB模型(尤其是十六进制),但我也经常发现它难以阅读和操作。让我们看一下HSL模型。HSLHSL是“色调、饱和度、亮度”的缩写,HSL也包含三个值。色调值对应于色轮上的点,由CSS角度值表示,最常见的单位是度。饱和度以百分比表示,指的是颜色的强度。饱和度为100%时颜色最深,饱和度越低颜色越浅,直到0%灰度。亮度也以百分比表示,指的是颜色的明亮程度。“正常”亮度为50%。无论色相和饱和度值如何,100%亮度为纯白色,0%亮度为纯黑色。我觉得HSL模型更直观,颜色之间的关系更明显。控制颜色时,只需简单地调整几个数字即可。在颜色模型之间转换RGB和HSL颜色模型都将颜色分解为各种属性。要在不同模型之间进行转换,我们首先需要计算这些属性。除了色相,上面提到的所有值都可以用百分比表示。甚至RGB值也以字节为单位表示为百分比。在下面提到的公式和函数中,这些百分比将由0到1之间的小数表示。提醒一下,我不会在这里深入研究数学;相反,我将简要介绍原始数学并将其转换为JavaScript。从RGB模型计算亮度亮度是三个HSL值中最容易计算的。其数学公式如下,其中M为RGB值的最大值,m为最小值:用JavaScript函数写成如下形式:constrgbToLightness=(r,g,b)=>1/2*(Math.max(r,g,b)+Math.min(r,g,b));从RGB模型计算饱和度饱和度只比亮度稍微复杂一点。如果亮度为0或1,则饱和度值为0;否则,它是根据以下数学公式计算的,其中L是亮度:用Ja??vaScript编写:constrgbToSaturation=(r,g,b)=>{constL=rgbToLightness(r,g,b);constmax=Math.max(r,g,b);constmin=Math.min(r,g,b);返回(L===0||L===1)?0:(max-min)/(1-Math.abs(2*L-1));};从RGB模型计算色调从RGB坐标计算色调角度的公式有点复杂:用Ja??vaScript编写:constrgbToHue=(r,g,b)=>Math.round(Math.atan2(Math.sqrt(3)*(g-b),2*r-g-b,)*180/Math.PI);最后180/Math.PI的算法是将结果从弧度转换为度。计算HSL以上函数都可以包含在同一个函数中:constrgbToHsl=(r,g,b)=>{constlightness=rgbToLightness(r,g,b);constsaturation=rgbToSaturation(r,g,b);consthue=rgbToHue(r,g,b);return[hue,saturation,lightness];}从HSL模型计算RGB值在我们开始计算RGB之前,我们需要一些先决条件值。首先是“色度”值:还有一个临时色调值,我们将使用它来确定我们属于色相圈的哪个“段”:接下来,我们设置一个“x”值,它将用作中间值(p.2)分量值:我们还有另一个“m”值,用于调整各个亮度值:r、g和b值将根据色调区间值映射到C、X和0:最后,我们需要映射每个值以调整亮度:将以上内容写入JavaScript函数:consthslToRgb=(h,s,l)=>{constC=(1-Math.abs(2*l-1))*s;consthPrime=h/60;constX=C*(1-Math.abs(hPrime%2-1));constm=l-C/2;常量withLight=(r,g,b)=>[r+m,g+m,b+m];if(hPrime<=1){returnwithLight(C,X,0);}elseif(hPrime<=2){returnwithLight(X,C,0);}elseif(hPrime<=3){returnwithLight(0,C,X);}elseif(hPrime<=4){returnwithLight(0,X,C);}elseif(hPrime<=5){returnwithLight(X,0,C);}elseif(hPrime<=6){returnwithLight(C,0,X);}}创建颜色对象为了在操作属性时方便访问,我们将创建一个JavaScript对象。这个对象可以通过封装上面提到的函数来创建:constrgbToObject=(red,green,blue)=>{const[hue,saturation,lightness]=rgbToHsl(red,green,blue);return{red,green,blue,hue,saturation,lightness};}consthslToObject=(hue,saturation,lightness)=>{const[red,green,blue]=hslToRgb(hue,saturation,lightness);}return{red,green,blue,hue,saturation,lightness};}颜色控制现在我们知道如何在颜色模型之间转换,让我们看看如何控制这些颜色!更新属性我们提到的所有颜色属性都可以单独操作,返回一个新的颜色对象。例如,我们可以编写一个旋转色调角度的函数:constrotateHue=rotation=>({hue,...rest})=>{constmodulo=(x,n)=>(x%n+n)%n;constnewHue=modulo(hue+rotation,360);return{...rest,hue:newHue};}rotateHue函数接受一个旋转参数并返回一个接受并返回颜色对象的新函数。这使得创建新的“旋转”功能变得容易:constrotate30=rotateHue(30);constgetComplementary=rotateHue(180);constgetTriadic=color=>{constfirst=rotateHue(120);constsecond=rotateHue(-120);return[first(color),second(color)];}这样,您还可以编写使颜色变暗或变亮的函数,反之亦然,使颜色变亮或变暗。constsaturate=x=>({saturation,...rest})=>({...rest,saturation:Math.min(1,saturation+x),});constdesaturate=x=>({saturation,...rest})=>({...rest,saturation:Math.max(0,saturation-x),});constlighten=x=>({lightness,...rest})=>({...rest,lightness:Math.min(1,lightness+x)});constdarken=x=>({lightness,...rest})=>({...rest,lightness:Math.max(0,lightness-x)});颜色谓词除了颜色控件,您还可以编写“谓词”——即返回布尔值的函数。constisGrayscale=({saturation})=>饱和度===0;constisDark=({lightness})=>亮度<.5;handlecolorarrayfilterJavaScript[].filter方法接受一个谓词并返回一个包含所有“通过”元素的新数组。我们在上一节中写的谓词可以在这里使用:constcolors=[/*...颜色对象数组...*/];constisLight=({lightness})=>亮度>.5;constlightColors=colors.filter(isLight);排序要对一组颜色进行排序,首先需要编写一个“比较器”函数。此函数采用数组的两个元素并返回代表“获胜者”的数字。正数表示第一个元素应该首先排序,而负数表示第二个元素应该首先排序。零值表示平局。例如,这里有一个比较两种颜色亮度的函数:constcompareLightness=(a,b)=>a.lightness-b.lightness;这是一个比较饱和度的函数:constcompareSaturation=(a,b)=>a.saturation-b.saturation;为了防止代码重复,我们可以写一个高阶函数返回一个比较函数来比较各种属性:constcompareAttribute=attribute=>(a,b)=>a[attribute]-b[attribute];constcompareLightness=compareAttribute('亮度');constcompareSaturation=compareAttribute('饱和度');constcompareHue=compareAttribute('色调');平均属性您可以使用各种JavaScript数组方法来平衡颜色数组的特定属性。首先,您可以使用reduce求和并除以数组长度属性来计算属性的平均值:constcolors=[/*...颜色对象数组...*/];consttoSum=(a,b)=>a+b;常量toAttribute=属性=>元素=>元素[属性];constaverageOfAttribute=attribute=>array=>array.map(toAttribute(attribute)).reduce(toSum)/array.length;你可以使用它“规范化”一个颜色数组:constnormalize=overwriteAttribute(属性)(averageValue);返回归一化(数组);}constnormalizeSaturation=normalizeAttribute('饱和度');constnormalizeLightness=normalizeAttribute('亮度');constnormalizeHue=normalizeAttribute('色调');结论颜色是网络不可或缺的一部分。将颜色分解为属性,可以让他们灵活地控制它们并创造无限的可能性。