Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
內(nèi)容首發(fā)于工粽號(hào):程序員大澈,每日分享一段優(yōu)質(zhì)代碼片段,歡迎關(guān)注和投稿!
大家好,我是大澈!
本文約 1100+ 字,整篇閱讀約需 2 分鐘。
今天分享一段優(yōu)質(zhì) CSS 代碼片段,應(yīng)用灰度效果,讓頁(yè)面變成黑白顯示。
老規(guī)矩,先閱讀代碼片段并思考,再看代碼解析再思考,最后評(píng)論區(qū)留下你的見(jiàn)解!
body {
filter: grayscale(1); // 1相當(dāng)于100%
}
分享原因
這段代碼展示了如何使用 CSS 濾鏡來(lái)將整個(gè)網(wǎng)頁(yè)變?yōu)榛叶刃Ч?/span>
在特殊的日子里,網(wǎng)頁(yè)有整體變灰色的需求,可以使用這段代碼,這個(gè)需求很有必要。
再就是做一些老照片或黑白電影的效果,也可以使用這段代碼。
代碼解析
1. 選擇器 body
這一部分選擇了 HTML 文檔的 <body> 元素,即整個(gè)網(wǎng)頁(yè)的主體。
CSS 的 filter 屬性通常用于圖像,但也可以應(yīng)用到其他任何 HTML 元素上。
2. grayscale(1);
grayscale 濾鏡將元素的顏色變成灰度效果。
參數(shù) 1 表示 100% 灰度,參數(shù) 0 表示無(wú)灰度效果。
3. filter 所有屬性值 大盤(pán)點(diǎn)!
CSS 的 filter 屬性提供了多種圖形效果,且這些屬性值可以組合用起來(lái),且可以應(yīng)用于任何元素。
以下是 filter 屬性的所有值及其詳細(xì)解釋:
blur()
功能:應(yīng)用模糊效果。
參數(shù):接受一個(gè)長(zhǎng)度值(如 px、em),默認(rèn)值是 0。
示例:filter: blur(5px);
brightness()
功能:調(diào)整圖像的亮度。
參數(shù):接受一個(gè)數(shù)值,1 為原始亮度。值小于 1 會(huì)降低亮度,值大于 1 會(huì)增加亮度。
示例:filter: brightness(0.5);
contrast()
功能:調(diào)整圖像的對(duì)比度。
參數(shù):接受一個(gè)數(shù)值,1 為原始對(duì)比度。值小于 1 會(huì)降低對(duì)比度,值大于 1 會(huì)增加對(duì)比度。
示例:filter: contrast(200%);
drop-shadow()
功能:應(yīng)用陰影效果。
參數(shù):類似于 box-shadow,包括偏移量、模糊半徑和顏色。
示例:filter: drop-shadow(10px 10px 10px #000);
grayscale()
功能:將圖像變?yōu)榛叶取?/span>
參數(shù):接受一個(gè) 0 到 1 之間的數(shù)值,0 為無(wú)灰度,1 為完全灰度。
示例:filter: grayscale(1);
hue-rotate()
功能:旋轉(zhuǎn)圖像的色相。
參數(shù):接受一個(gè)角度值,單位為度(deg)。
示例:filter: hue-rotate(90deg);
invert()
功能:反轉(zhuǎn)圖像的顏色。
參數(shù):接受一個(gè) 0 到 1 之間的數(shù)值,0 為無(wú)效果,1 為完全反轉(zhuǎn)。
示例:filter: invert(1);
opacity()
功能:調(diào)整圖像的透明度。
參數(shù):接受一個(gè) 0 到 1 之間的數(shù)值,0 為完全透明,1 為完全不透明。
示例:filter: opacity(0.5);
saturate()
功能:調(diào)整圖像的飽和度。
參數(shù):接受一個(gè)數(shù)值,1 為原始飽和度。值小于 1 會(huì)降低飽和度,值大于 1 會(huì)增加飽和度。
示例:filter: saturate(2);
sepia()
功能:將圖像變?yōu)樽睾稚?/span>
參數(shù):接受一個(gè) 0 到 1 之間的數(shù)值,0 為無(wú)效果,1 為完全棕褐色。
示例:filter: sepia(1);
url()
功能:引用 SVG 濾鏡。
參數(shù):接受一個(gè) URL,指向一個(gè)包含 SVG 濾鏡的文件。
示例:filter: url(#filter-id);
- end -
篇文章面向那些已經(jīng)熟練使用for循環(huán),但對(duì)Array.map和Array.filter并沒(méi)有特別理解的開(kāi)發(fā)者。本文將會(huì)手把手去實(shí)現(xiàn)這兩個(gè)函數(shù),來(lái)深入理解它們的工作原理。
Array.map
Array.map通過(guò)對(duì)輸入的數(shù)組中每一個(gè)元素進(jìn)行變換,返回由變換后的元素按序組成的新數(shù)組。原始數(shù)組的值不會(huì)被修改。假設(shè)我們相對(duì)一個(gè)數(shù)組中的每一個(gè)元素乘以3,使用for循環(huán)可以這樣寫(xiě)。
for循環(huán)
var originalArr = [1, 2, 3, 4, 5]; var newArr = []; for(var i = 0; i < originalArr.length; i++) { newArr[i] = originalArr[i] * 3; } console.log(newArr); // -> [3, 6, 9, 12, 15]
接下來(lái)我們將這個(gè)for循環(huán)抽象成一個(gè)函數(shù)。
multiplyByThree函數(shù)
var originalArr = [1, 2, 3, 4, 5]; function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = arr[i] * 3; } return newArr; } var arrTransformed = multiplyByThree(originalArr); console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
現(xiàn)在我們繼續(xù)深化這個(gè)抽象思路,將multiplyByThree中對(duì)每一個(gè)元素乘以3部分抽象為一個(gè)新的函數(shù)。
var originalArr = [1, 2, 3, 4, 5]; function timesThree(item) { return item * 3; } function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = timesThree(arr[i]); } return newArr; } var arrTransformed = multiplyByThree(originalArr); console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
這樣有什么好處呢?設(shè)想如果我們想對(duì)每一個(gè)元素乘以5,或則10,我們還要把整個(gè)for循環(huán)寫(xiě)一遍嗎!
如果我們對(duì)timesThree函數(shù)稍作修改,就可以輕松的復(fù)用很多代碼。
multiply函數(shù)
我們將:
function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = timesThree(arr[i]); } return newArr; }
重構(gòu)為:
function multiply(arr, multiplyFunction) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = multiplyFunction(arr[i]); } return newArr; }
我們將multiplyByThree重命名為multiply,并增加了一個(gè)參數(shù)。該參數(shù)是一個(gè)函數(shù),定義了數(shù)組元素的變換規(guī)則。通過(guò)定義一個(gè)timesThree函數(shù)來(lái)達(dá)到實(shí)現(xiàn)對(duì)每一個(gè)數(shù)組元素乘以3的目的。
var originalArr = [1, 2, 3, 4, 5]; function timesThree(item) { return item * 3; } var arrTimesThree = multiply(originalArr, timesThree); console.log(arrTimesThree); // -> [3, 6, 9, 12, 15]
有何優(yōu)點(diǎn)呢?我們可以很簡(jiǎn)單定義任何變換:
var originalArr = [1, 2, 3, 4, 5]; function timesFive(item) { return item * 5; } var arrTimesFive = multiply(originalArr, timesFive); console.log(arrTimesFive); // -> [5, 10, 15, 20, 25]
Map
我們進(jìn)一步抽象:
function multiply(arr, multiplyFunction) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = multiplyFunction(arr[i]); } return newArr; }
將multiply改為map, multiplyFunction改為transform:
function map(arr, transform) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = transform(arr[i]); } return newArr; }
我們可以將任何對(duì)單個(gè)元素操作的函數(shù)傳入map函數(shù)。比如,我們將所有字符都變換成大寫(xiě):
function makeUpperCase(str) { return str.toUpperCase(); } var arr = ['abc', 'def', 'ghi']; var ARR = map(arr, makeUpperCase); console.log(ARR); // -> ['ABC', 'DEF, 'GHI']
Array.map
我們定義的map函數(shù)和原生的Array.map還是有區(qū)別的:數(shù)組不再需要作為第一個(gè)參數(shù)傳入,而是在點(diǎn)(.)的左側(cè)。如果使用我們定義的map函數(shù),如下:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = map(arr, func); console.log(newArr); // -> [3, 6, 9]
將其改寫(xiě)為使用Array.map函數(shù)的形式:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = arr.map(func); console.log(newArr); // -> [3, 6, 9]
Arrary.map參數(shù)解析
除了變換函數(shù)外,Array.map還可以接收其它兩個(gè)參數(shù): 數(shù)組索引(index), 原始的數(shù)組。
function logItem(item) { console.log(item); } function logAll(item, index, arr) { console.log(item, index, arr); } var arr = ['abc', 'def', 'ghi']; arr.map(logItem); // -> 'abc', 'def', 'ghi' arr.map(logAll); // -> 'abc', 0, ['abc', 'def', 'ghi'] // -> 'def', 1, ['abc', 'def', 'ghi'] // -> 'ghi', 2, ['abc', 'def', 'ghi']
因此,你可以再變換函數(shù)中使用索引和原始的數(shù)組。比如:你想要將一個(gè)列表變?yōu)閹蛱?hào)的列表,則需要使用索引(index)參數(shù):
function multiplyByIndex(item, index) { return (index + 1) + '. ' + item; } var arr = ['bananas', 'tomatoes', 'pasta', 'protein shakes']; var mappedArr = arr.map(multiplyByIndex); console.log(mappedArr); // -> // ["1. bananas", "2. tomatoes", "3. pasta", "4. protein shakes"]
因此,我們自己實(shí)現(xiàn)的map函數(shù)也應(yīng)該支持這兩個(gè)參數(shù):
function map(arr, transform) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = transform(arr[i], i, arr); } return newArr; }
當(dāng)然,Array.map函數(shù)還有一些錯(cuò)誤檢查和執(zhí)行優(yōu)化的代碼,我們定義的map只編碼了核心功能。
Array.filter
Array.filter將數(shù)組中不滿足條件的元素過(guò)濾,我們可以用for循環(huán)加上Array.push來(lái)實(shí)現(xiàn)。
for-loop
下面這段JS代碼將所有大于5的元素篩選出來(lái):
var arr = [2, 4, 6, 8, 10]; var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(arr[i] > 5) { filteredArr.push(arr[i]); } } console.log(filteredArr); // -> [6, 8, 10]
我們可以抽象這段代碼,定義為一個(gè)函數(shù):
function filterLessThanFive(arr) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(arr[i] > 5){ filteredArr.push(arr[i]); } } return filteredArr; } var arr1 = [2, 4, 6, 8, 10]; var arr1Filtered = filterLessThanFive(arr1); console.log(arr1Filtered); // -> [6, 8, 10]
進(jìn)一步抽象,將過(guò)濾條件抽出來(lái):
function isGreaterThan5(item) { return item > 5; } function filterLessThanFive(arr) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(isGreaterThan5(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; } var originalArr = [2, 4, 6, 8, 10]; var newArr = filterLessThanFive(originalArr); console.log(newArr); // -> [6, 8, 10]
將過(guò)濾條件函數(shù)作為參數(shù)傳入:
function filterBelow(arr, greaterThan) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(greaterThan(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; } var originalArr = [2, 4, 6, 8, 10];
大功告成!我們可以使用如下代碼來(lái)取出所有大于5的元素:
function isGreaterThan5(item) { return item > 5; } var newArr = filterBelow(originalArr, isGreaterThan5); console.log(newArr); // -> [6, 8, 10];
Array.filter
我們將filterBelow重命名為filter, greaterThan重命名為testFunction:
function filter(arr, testFunction) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(testFunction(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; }
這就是一個(gè)基本的Array.filter函數(shù)了!
var arr = ['abc', 'def', 'ghijkl', 'mnopuv']; function longerThanThree(str) { return str.length > 3; } var newArr1 = filter(arr, longerThanThree); var newArr2 = arr.filter(longerThanThree); console.log(newArr1); // -> ['ghijkl', 'mnopuv'] console.log(newArr2); // -> ['ghijkl', 'mnopuv']
同樣,Array.filter也有索引(index)和原始數(shù)組這兩個(gè)額外參數(shù)。
function func(item, index, arr) { console.log(item, index, arr); } var arr = ['abc', 'def', 'ghi']; arr.filter(func); // -> 'abc', 0, ['abc', 'def', 'ghi'] // -> 'def', 1, ['abc', 'def', 'ghi'] // -> 'ghi', 2, ['abc', 'def', 'ghi']
關(guān)于Fundebug
Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了7億+錯(cuò)誤事件,得到了Google、360、金山軟件、百姓網(wǎng)等眾多知名用戶的認(rèn)可。歡迎免費(fèi)試用
以上就是小編的分享,感謝各位大佬們耐心的看完文章,最后再分享一個(gè)我自己的后端技術(shù)群,群里自己收集了很多Java架構(gòu)資料,大家可以進(jìn)群免費(fèi)領(lǐng)取資料,群號(hào):680075317,也可以進(jìn)群一起交流,比如遇到技術(shù)瓶頸、面試不過(guò)的,大家一些交流學(xué)習(xí)!
23 年的 CSS 新特性中,有一個(gè)非常重要的功能更新 -- 相對(duì)顏色。
簡(jiǎn)單而言,相對(duì)顏色的功能,讓我們?cè)?CSS 中,對(duì)顏色有了更為強(qiáng)大的掌控能力。
其核心功能就是,讓我們能夠基于一個(gè)現(xiàn)有顏色 A,通過(guò)一定的轉(zhuǎn)換規(guī)則,快速生成我們想要的顏色 B。
其功能能夠涵蓋:
當(dāng)然,今天我們不會(huì)一個(gè)一個(gè)去過(guò)這些功能,更多的時(shí)候,我們只需要知道我們能夠?qū)崿F(xiàn)這些功能。
本文,我們將從實(shí)際實(shí)用角度出發(fā),基于實(shí)際的案例,看看 CSS 相對(duì)顏色,能夠如何解決我們的一些實(shí)際問(wèn)題。
首先,我們通過(guò)一張圖,一個(gè)案例,快速入門(mén) CSS 相對(duì)顏色語(yǔ)法:
相對(duì)顏色語(yǔ)法的目標(biāo)是允許從另一種顏色派生顏色。
上圖顯示了將原始顏色 green 轉(zhuǎn)換為新顏色的顏色空間后,該顏色會(huì)轉(zhuǎn)換為以 r、g、b 和 alpha 變量表示的各個(gè)數(shù)字,這些數(shù)字隨后會(huì)直接用作新的 rgb() 顏色的值。
舉個(gè)例子:
<p> CSS Relative Color </p>
p {
color: rgb(255, 0, 0);
}
實(shí)現(xiàn)一個(gè) color 為紅色(rgb 值為 rgb(255, 0, 0))的字體:
基于上面的相對(duì)顏色語(yǔ)法,我如何通過(guò)一個(gè)紅色生成綠色文字呢?示意如下:
p {
--color: rgb(255, 0, 0);
color: rgb(from var(--color) calc(r - 255) calc(g + 255) b); /* result = rgb(0, 255, 0) */
}
效果如下,我們就得到綠色字體:
解釋一下:
通過(guò)這個(gè) DEMO,我們把幾個(gè)核心基礎(chǔ)語(yǔ)法點(diǎn)學(xué)習(xí)一下:
from 關(guān)鍵字,它是相對(duì)顏色的核心。它表示會(huì)將 from 關(guān)鍵字后的顏色定義轉(zhuǎn)換為相對(duì)顏色!在 from 關(guān)鍵字后面,CSS 會(huì)期待一種顏色,即能夠啟發(fā)生成另一種顏色。
第二個(gè)關(guān)鍵點(diǎn),from 后面通常會(huì)接一個(gè)顏色值,這個(gè)顏色值可以是任意顏色表示法,或者是一個(gè) CSS 變量,下面的寫(xiě)法都是合法的:
p {
color: rgba(from #ff0000) r g b);
color: rgb(from rgb(255, 0, 0) r g b);
color: rgb(from hsl(0deg, 100%, 50%) r g b);
color: rgb(from var(--hotpink) r g b);
}
另外一個(gè)非常重要的基礎(chǔ)概念就是,我們可以對(duì) (from color r g b) 后的轉(zhuǎn)換變量 r g b 使用 calc() 或其他 CSS 函數(shù)。
就是我們上面的例子:
p {
--color: rgb(255, 0, 0);
color: rgb(from var(--color) calc(r - 255) calc(g + 255) b); /* result = rgb(0, 255, 0) */
}
相對(duì)顏色的基礎(chǔ)的使用規(guī)則就是這樣,它不僅支持 rgb 顏色表示法,它支持所有的顏色表示法:
通常頁(yè)面上的按鈕,都會(huì)有 hover/active 的顏色變化,以增強(qiáng)與用戶的交互。
像是這樣:
最常見(jiàn)的寫(xiě)法,就是我們需要在 Normal 狀態(tài)、Hover 狀態(tài)、Active 狀態(tài)下寫(xiě) 3 種顏色:
p {
color: #ffcc00;
transition: .3s all;
}
/* Hover 偽類下為 B 顏色 */
p:hover {
color: #ffd21f;
}
/** Active 偽類下為 C 顏色 **/
p:active {
color: #ab8a05;
}
在之前,我們介紹過(guò)一種利用濾鏡 filter: contrast() 或者 filter: brightness() 的統(tǒng)一解決方案,無(wú)需寫(xiě)多個(gè)顏色值,可以根據(jù) Normal 狀態(tài)下的色值,通過(guò)濾鏡統(tǒng)一實(shí)現(xiàn)更亮、或者更暗的偽類顏色。
在今天,我們也可以利用 CSS 相對(duì)顏色來(lái)做這個(gè)事情:
div {
--bg: #fc0;
background: var(--bg);
transition: .3s all;
}
div:hover {
background: hsl(from var(--bg) h s calc(l * 1.2));
}
div:active {
background: hsl(from var(--bg) h s calc(l * 0.8));
}
我們通過(guò) hsl 色相、飽和度、亮度顏色表示法表示顏色。實(shí)現(xiàn):
在實(shí)際業(yè)務(wù)中,這是一個(gè)非常有用的用法。
相對(duì)顏色,還有一個(gè)非常有意思的場(chǎng)景 -- 讓文字顏色能夠自適應(yīng)背景顏色進(jìn)行展示。
有這么一種場(chǎng)景,有的時(shí)候,無(wú)法確定文案的背景顏色的最終表現(xiàn)值(因?yàn)楸尘邦伾闹悼赡苁呛笈_(tái)配置,通過(guò)接口傳給前端),但是,我們又需要能夠讓文字在任何背景顏色下都正常展現(xiàn)(譬如當(dāng)?shù)咨珵楹谏珪r(shí)文字應(yīng)該是白色,當(dāng)背景為白色時(shí),文字應(yīng)該為黑色)。
像是這樣:
在不確定背景顏色的情況下,無(wú)論什么情況,文字顏色都能夠適配背景的顏色。
在之前,純 CSS 沒(méi)有特別好的方案,可以利用 mix-blend-mode: difference 進(jìn)行一定程度的適配:
div {
// 不確定的背景色
}
p {
color: #fff;
mix-blend-mode: difference;
}
實(shí)操過(guò)這個(gè)方案的同學(xué)都會(huì)知道,在一定情況下,前景文字顏色還是會(huì)有一點(diǎn)瑕疵。并且,混合模式這個(gè)方案最大的問(wèn)題是會(huì)影響清晰度。
有了 CSS 相對(duì)顏色后,我們有了更多的純 CSS 方案。
我們可以利用相對(duì)顏色的能力,基于背景色顏色進(jìn)行反轉(zhuǎn),賦值給 color。
一種方法是將顏色轉(zhuǎn)換為 RGB,然后從 1 中減去每個(gè)通道的值。
代碼非常簡(jiǎn)單:
p {
/** 任意背景色 **/
--bg: #ffcc00;
background: var(--bg);
color: rgb(from var(--bg) calc(1 - r) calc(1 - g) calc(1 - b)); /** 基于背景反轉(zhuǎn)顏色 **/
}
用 1 去減,而不是用 255 去,是因?yàn)榇丝蹋瑫?huì)將 rgb() 表示法中的 0~255 映射到 0~1。
效果如下:
配個(gè)動(dòng)圖,我們利用背景色的反色當(dāng) Color 顏色,適配所有背景情況:
完整的 DEMO 和代碼,你可以戳這里:CodePen Demo -- CSS Relatvie Color Adapt BG
當(dāng)然,這個(gè)方案還有兩個(gè)問(wèn)題:
為了解決這兩個(gè)問(wèn)題,CSS 顏色規(guī)范在 CSS Color Module Level 6 又推出了一個(gè)新的規(guī)范 -- color-contrast()。
color-contrast() 函數(shù)標(biāo)記接收一個(gè) color 值,并將其與其他的 color 值比較,從列表中選擇最高對(duì)比度的顏色。
利用這個(gè) CSS 顏色函數(shù),可以完美的解決上述的問(wèn)題。
我們只需要提供 #fff 白色和 #000 黑色兩種可選顏色,將這兩種顏色和提供的背景色進(jìn)行比較,系統(tǒng)會(huì)自動(dòng)選取對(duì)比度更高的顏色。
改造一下,上面的代碼,它就變成了:
p {
/** 任意背景色 **/
--bg: #ffcc00;
background: var(--bg);
color: color-contrast(var(--bg) vs #fff, #000); /** 基于背景色,自動(dòng)選擇對(duì)比度更高的顏色 **/
}
這樣,上面的 DEMO 最終效果就變成了:
此方案的優(yōu)勢(shì)在于:
當(dāng)然,唯一限制這個(gè)方案的最大問(wèn)題在于,當(dāng)前,color-contrast 還只是一個(gè)實(shí)驗(yàn)室功能,未大規(guī)模被兼容。
到今天,我們可以利用 CSS 提供的各類顏色函數(shù),對(duì)顏色有了更為強(qiáng)大的掌控力。
很多交互效果,不借助 JavaScript 的運(yùn)算,也能計(jì)算出我們想要的最終顏色值。本文簡(jiǎn)單的借助:
兩個(gè)案例,介紹了 CSS 相對(duì)顏色的功能。
原文鏈接:https://juejin.cn/post/7321410822789742618
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。