內容首發于工粽號:程序員大澈,每日分享一段優質代碼片段,歡迎關注和投稿!
大家好,我是大澈!
本文約 1100+ 字,整篇閱讀約需 2 分鐘。
今天分享一段優質 CSS 代碼片段,應用灰度效果,讓頁面變成黑白顯示。
老規矩,先閱讀代碼片段并思考,再看代碼解析再思考,最后評論區留下你的見解!
body {
filter: grayscale(1); // 1相當于100%
}
分享原因
這段代碼展示了如何使用 CSS 濾鏡來將整個網頁變為灰度效果。
在特殊的日子里,網頁有整體變灰色的需求,可以使用這段代碼,這個需求很有必要。
再就是做一些老照片或黑白電影的效果,也可以使用這段代碼。
代碼解析
1. 選擇器 body
這一部分選擇了 HTML 文檔的 <body> 元素,即整個網頁的主體。
CSS 的 filter 屬性通常用于圖像,但也可以應用到其他任何 HTML 元素上。
2. grayscale(1);
grayscale 濾鏡將元素的顏色變成灰度效果。
參數 1 表示 100% 灰度,參數 0 表示無灰度效果。
3. filter 所有屬性值 大盤點!
CSS 的 filter 屬性提供了多種圖形效果,且這些屬性值可以組合用起來,且可以應用于任何元素。
以下是 filter 屬性的所有值及其詳細解釋:
blur()
功能:應用模糊效果。
參數:接受一個長度值(如 px、em),默認值是 0。
示例:filter: blur(5px);
brightness()
功能:調整圖像的亮度。
參數:接受一個數值,1 為原始亮度。值小于 1 會降低亮度,值大于 1 會增加亮度。
示例:filter: brightness(0.5);
contrast()
功能:調整圖像的對比度。
參數:接受一個數值,1 為原始對比度。值小于 1 會降低對比度,值大于 1 會增加對比度。
示例:filter: contrast(200%);
drop-shadow()
功能:應用陰影效果。
參數:類似于 box-shadow,包括偏移量、模糊半徑和顏色。
示例:filter: drop-shadow(10px 10px 10px #000);
grayscale()
功能:將圖像變為灰度。
參數:接受一個 0 到 1 之間的數值,0 為無灰度,1 為完全灰度。
示例:filter: grayscale(1);
hue-rotate()
功能:旋轉圖像的色相。
參數:接受一個角度值,單位為度(deg)。
示例:filter: hue-rotate(90deg);
invert()
功能:反轉圖像的顏色。
參數:接受一個 0 到 1 之間的數值,0 為無效果,1 為完全反轉。
示例:filter: invert(1);
opacity()
功能:調整圖像的透明度。
參數:接受一個 0 到 1 之間的數值,0 為完全透明,1 為完全不透明。
示例:filter: opacity(0.5);
saturate()
功能:調整圖像的飽和度。
參數:接受一個數值,1 為原始飽和度。值小于 1 會降低飽和度,值大于 1 會增加飽和度。
示例:filter: saturate(2);
sepia()
功能:將圖像變為棕褐色。
參數:接受一個 0 到 1 之間的數值,0 為無效果,1 為完全棕褐色。
示例:filter: sepia(1);
url()
功能:引用 SVG 濾鏡。
參數:接受一個 URL,指向一個包含 SVG 濾鏡的文件。
示例:filter: url(#filter-id);
- end -
篇文章面向那些已經熟練使用for循環,但對Array.map和Array.filter并沒有特別理解的開發者。本文將會手把手去實現這兩個函數,來深入理解它們的工作原理。
Array.map
Array.map通過對輸入的數組中每一個元素進行變換,返回由變換后的元素按序組成的新數組。原始數組的值不會被修改。假設我們相對一個數組中的每一個元素乘以3,使用for循環可以這樣寫。
for循環
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]
接下來我們將這個for循環抽象成一個函數。
multiplyByThree函數
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]
現在我們繼續深化這個抽象思路,將multiplyByThree中對每一個元素乘以3部分抽象為一個新的函數。
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]
這樣有什么好處呢?設想如果我們想對每一個元素乘以5,或則10,我們還要把整個for循環寫一遍嗎!
如果我們對timesThree函數稍作修改,就可以輕松的復用很多代碼。
multiply函數
我們將:
function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = timesThree(arr[i]); } return newArr; }
重構為:
function multiply(arr, multiplyFunction) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = multiplyFunction(arr[i]); } return newArr; }
我們將multiplyByThree重命名為multiply,并增加了一個參數。該參數是一個函數,定義了數組元素的變換規則。通過定義一個timesThree函數來達到實現對每一個數組元素乘以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]
有何優點呢?我們可以很簡單定義任何變換:
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
我們進一步抽象:
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; }
我們可以將任何對單個元素操作的函數傳入map函數。比如,我們將所有字符都變換成大寫:
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函數和原生的Array.map還是有區別的:數組不再需要作為第一個參數傳入,而是在點(.)的左側。如果使用我們定義的map函數,如下:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = map(arr, func); console.log(newArr); // -> [3, 6, 9]
將其改寫為使用Array.map函數的形式:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = arr.map(func); console.log(newArr); // -> [3, 6, 9]
Arrary.map參數解析
除了變換函數外,Array.map還可以接收其它兩個參數: 數組索引(index), 原始的數組。
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']
因此,你可以再變換函數中使用索引和原始的數組。比如:你想要將一個列表變為帶序號的列表,則需要使用索引(index)參數:
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"]
因此,我們自己實現的map函數也應該支持這兩個參數:
function map(arr, transform) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = transform(arr[i], i, arr); } return newArr; }
當然,Array.map函數還有一些錯誤檢查和執行優化的代碼,我們定義的map只編碼了核心功能。
Array.filter
Array.filter將數組中不滿足條件的元素過濾,我們可以用for循環加上Array.push來實現。
for-loop
下面這段JS代碼將所有大于5的元素篩選出來:
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]
我們可以抽象這段代碼,定義為一個函數:
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]
進一步抽象,將過濾條件抽出來:
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]
將過濾條件函數作為參數傳入:
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];
大功告成!我們可以使用如下代碼來取出所有大于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; }
這就是一個基本的Array.filter函數了!
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)和原始數組這兩個額外參數。
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']
關于Fundebug
Fundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了7億+錯誤事件,得到了Google、360、金山軟件、百姓網等眾多知名用戶的認可。歡迎免費試用
以上就是小編的分享,感謝各位大佬們耐心的看完文章,最后再分享一個我自己的后端技術群,群里自己收集了很多Java架構資料,大家可以進群免費領取資料,群號:680075317,也可以進群一起交流,比如遇到技術瓶頸、面試不過的,大家一些交流學習!
23 年的 CSS 新特性中,有一個非常重要的功能更新 -- 相對顏色。
簡單而言,相對顏色的功能,讓我們在 CSS 中,對顏色有了更為強大的掌控能力。
其核心功能就是,讓我們能夠基于一個現有顏色 A,通過一定的轉換規則,快速生成我們想要的顏色 B。
其功能能夠涵蓋:
當然,今天我們不會一個一個去過這些功能,更多的時候,我們只需要知道我們能夠實現這些功能。
本文,我們將從實際實用角度出發,基于實際的案例,看看 CSS 相對顏色,能夠如何解決我們的一些實際問題。
首先,我們通過一張圖,一個案例,快速入門 CSS 相對顏色語法:
相對顏色語法的目標是允許從另一種顏色派生顏色。
上圖顯示了將原始顏色 green 轉換為新顏色的顏色空間后,該顏色會轉換為以 r、g、b 和 alpha 變量表示的各個數字,這些數字隨后會直接用作新的 rgb() 顏色的值。
舉個例子:
<p> CSS Relative Color </p>
p {
color: rgb(255, 0, 0);
}
實現一個 color 為紅色(rgb 值為 rgb(255, 0, 0))的字體:
基于上面的相對顏色語法,我如何通過一個紅色生成綠色文字呢?示意如下:
p {
--color: rgb(255, 0, 0);
color: rgb(from var(--color) calc(r - 255) calc(g + 255) b); /* result = rgb(0, 255, 0) */
}
效果如下,我們就得到綠色字體:
解釋一下:
通過這個 DEMO,我們把幾個核心基礎語法點學習一下:
from 關鍵字,它是相對顏色的核心。它表示會將 from 關鍵字后的顏色定義轉換為相對顏色!在 from 關鍵字后面,CSS 會期待一種顏色,即能夠啟發生成另一種顏色。
第二個關鍵點,from 后面通常會接一個顏色值,這個顏色值可以是任意顏色表示法,或者是一個 CSS 變量,下面的寫法都是合法的:
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);
}
另外一個非常重要的基礎概念就是,我們可以對 (from color r g b) 后的轉換變量 r g b 使用 calc() 或其他 CSS 函數。
就是我們上面的例子:
p {
--color: rgb(255, 0, 0);
color: rgb(from var(--color) calc(r - 255) calc(g + 255) b); /* result = rgb(0, 255, 0) */
}
相對顏色的基礎的使用規則就是這樣,它不僅支持 rgb 顏色表示法,它支持所有的顏色表示法:
通常頁面上的按鈕,都會有 hover/active 的顏色變化,以增強與用戶的交互。
像是這樣:
最常見的寫法,就是我們需要在 Normal 狀態、Hover 狀態、Active 狀態下寫 3 種顏色:
p {
color: #ffcc00;
transition: .3s all;
}
/* Hover 偽類下為 B 顏色 */
p:hover {
color: #ffd21f;
}
/** Active 偽類下為 C 顏色 **/
p:active {
color: #ab8a05;
}
在之前,我們介紹過一種利用濾鏡 filter: contrast() 或者 filter: brightness() 的統一解決方案,無需寫多個顏色值,可以根據 Normal 狀態下的色值,通過濾鏡統一實現更亮、或者更暗的偽類顏色。
在今天,我們也可以利用 CSS 相對顏色來做這個事情:
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));
}
我們通過 hsl 色相、飽和度、亮度顏色表示法表示顏色。實現:
在實際業務中,這是一個非常有用的用法。
相對顏色,還有一個非常有意思的場景 -- 讓文字顏色能夠自適應背景顏色進行展示。
有這么一種場景,有的時候,無法確定文案的背景顏色的最終表現值(因為背景顏色的值可能是后臺配置,通過接口傳給前端),但是,我們又需要能夠讓文字在任何背景顏色下都正常展現(譬如當底色為黑色時文字應該是白色,當背景為白色時,文字應該為黑色)。
像是這樣:
在不確定背景顏色的情況下,無論什么情況,文字顏色都能夠適配背景的顏色。
在之前,純 CSS 沒有特別好的方案,可以利用 mix-blend-mode: difference 進行一定程度的適配:
div {
// 不確定的背景色
}
p {
color: #fff;
mix-blend-mode: difference;
}
實操過這個方案的同學都會知道,在一定情況下,前景文字顏色還是會有一點瑕疵。并且,混合模式這個方案最大的問題是會影響清晰度。
有了 CSS 相對顏色后,我們有了更多的純 CSS 方案。
我們可以利用相對顏色的能力,基于背景色顏色進行反轉,賦值給 color。
一種方法是將顏色轉換為 RGB,然后從 1 中減去每個通道的值。
代碼非常簡單:
p {
/** 任意背景色 **/
--bg: #ffcc00;
background: var(--bg);
color: rgb(from var(--bg) calc(1 - r) calc(1 - g) calc(1 - b)); /** 基于背景反轉顏色 **/
}
用 1 去減,而不是用 255 去,是因為此刻,會將 rgb() 表示法中的 0~255 映射到 0~1。
效果如下:
配個動圖,我們利用背景色的反色當 Color 顏色,適配所有背景情況:
完整的 DEMO 和代碼,你可以戳這里:CodePen Demo -- CSS Relatvie Color Adapt BG
當然,這個方案還有兩個問題:
為了解決這兩個問題,CSS 顏色規范在 CSS Color Module Level 6 又推出了一個新的規范 -- color-contrast()。
color-contrast() 函數標記接收一個 color 值,并將其與其他的 color 值比較,從列表中選擇最高對比度的顏色。
利用這個 CSS 顏色函數,可以完美的解決上述的問題。
我們只需要提供 #fff 白色和 #000 黑色兩種可選顏色,將這兩種顏色和提供的背景色進行比較,系統會自動選取對比度更高的顏色。
改造一下,上面的代碼,它就變成了:
p {
/** 任意背景色 **/
--bg: #ffcc00;
background: var(--bg);
color: color-contrast(var(--bg) vs #fff, #000); /** 基于背景色,自動選擇對比度更高的顏色 **/
}
這樣,上面的 DEMO 最終效果就變成了:
此方案的優勢在于:
當然,唯一限制這個方案的最大問題在于,當前,color-contrast 還只是一個實驗室功能,未大規模被兼容。
到今天,我們可以利用 CSS 提供的各類顏色函數,對顏色有了更為強大的掌控力。
很多交互效果,不借助 JavaScript 的運算,也能計算出我們想要的最終顏色值。本文簡單的借助:
兩個案例,介紹了 CSS 相對顏色的功能。
原文鏈接:https://juejin.cn/post/7321410822789742618
*請認真填寫需求信息,我們會在24小時內與您取得聯系。