宣告:本文涉及圖文和模型素材僅用於個人學習、研究和欣賞,請勿二次修改、非法傳播、轉載、出版、商用、及進行其他獲利行為。
背景
《聲生不息》 是芒果TV、香港電視廣播有限公司和湖南衛視聯合推出的港樂競唱獻禮節目,聽著音樂彷彿回到了那個令人懷念的港風席捲整個亞洲的年代。
該節目 Logo
採用經典紅藍配色,無限符號 ∞
造型,滿滿的設計感。本文在僅採用原生 CSS
的情況下,儘量還原實現該 Logo
造型,本文內容雖然非常簡單,但是用到的知識點挺多的,比如:repeating-linear-gradient
、clip-path
、background-clip
、Window.getComputedStyle()
、CSSStyleDeclaration.getPropertyValue()
等。
效果
先來看看實現效果吧。
點選右上角的 半圓
形狀,頁面主體可切換為白色。
線上預覽
??
Github:https://dragonir.github.io/sh...??
Codepen:https://codepen.io/dragonir/f...
實現
開始之前,先把 Logo
中用到的主要顏色作為CSS變數,後續會在多處用到這幾種顏色,並要通過變數實現頁面主體顏色切換功能。
:root {
--black: #010101;
--red: #F66034;
--blue: #0A68DF;
}
步驟0:第一個圓 ?
觀察 Logo
原型可以發現,第一個 ?
是純紅色條紋樣式效果,可以通過 repeating-linear-gradient
實現條紋背景效果,並設定偽元素 ::after
為背景黑色實現圓環樣式。
<div class="logo">
<div class="cycle cycle_1"></div>
</div>
.cycle {
height: 500px;
width: 500px;
border-radius: 50%;
position: relative;
box-sizing: border-box;
}
.cycle_1 {
z-index: 2;
background: var(--red);
background: repeating-linear-gradient(180deg,var(--red),var(--red) 12px, var(--black) 0, var(--black) 22px);
border: 12px solid var(--black);
}
.cycle_1::after {
content: '';
display: inline-block;
height: 200px;
width: 200px;
background: var(--black);
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
border-radius: 50%;
z-index: 3;
}
?
repeating-linear-gradient
repeating-linear-gradient
建立一個由重複線性漸變組成的 <image>
,和 linear-gradient
採用相同的引數,但它會在所有方向上重複漸變以覆蓋其整個容器。
語法:
repeating-linear-gradient([ <angle> | to <side-or-corner> ,]? <color-stop> [, <color-stop>]+ )
\---------------------------------/ \----------------------------/
漸變軸的定義 色標列表
<side-or-corner>
:描述漸變線的起始點位置。它包含兩個關鍵詞:第一個指出垂直位置left
或right
,第二個指出水平位置top
或bottom
。關鍵詞的先後順序無影響,且都是可選的。to top
,to bottom
,to left
和to right
這些值會被轉換成角度0度
、180度
、270度
和90度
。其餘值會被轉換為一個以向頂部中央方向為起點順時針旋轉的角度。漸變線的結束點與其起點中心對稱。<angle>
:用角度值指定漸變的方向或角度。角度順時針增加。<color-stop>
:由一個<color>
值組成,並且跟隨著一個可選的終點位置,可以是一個<percentage>
或者是沿著漸變軸的<length>
。
示例:
// 一個傾斜45度的重複線性漸變, 從藍色開始漸變到紅色
repeating-linear-gradient(45deg, blue, red);
// 一個由下至上的重複線性漸變, 從藍色開始,40%後變綠,最後漸變到紅色
repeating-linear-gradient(0deg, blue, green 40%, red);
?
每次重複,色標位置的偏移量都是基準漸變長度(最後一個色標和第一個之間的距離)的倍數。因此,最後色標的色值應該與第一個色標的色值保持一致;如果不一致的話,會導致非常突兀的漸變效果。?
與其他漸變一樣,線形重複漸變沒有提供固定的尺寸;即, 它沒有原始尺寸或首選尺寸,也沒有首選的比例。它將自適應於對應元素的尺寸。
步驟1:第二個圓 ?
新增第二個圓 ?
置於第一個圓 ?
的底層,它的樣式是從左到右的徑向漸變,通過 linear-gradient
即可實現。
<div class="logo">
<div class="cycle cycle_1"></div>
<div class="cycle cycle_2"></div>
</div>
.cycle_2 {
margin-left: -160px;
background: linear-gradient(to right, var(--red), var(--blue));
border: 12px solid var(--black);
}
.cycle_2::after {
content: '';
display: inline-block;
height: 200px;
width: 200px;
background: var(--black);
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
border-radius: 50%;
z-index: 3;
}
步驟2:兩個圓的重疊部分 ??
底部重疊部分,使用 clip-path
裁切出一個半圓效果,置於所有最頂層。
.cycle_2::before {
position: absolute;
box-sizing: border-box;
top: -12px;
left: -12px;
content: '';
display: inline-block;
height: 500px;
width: 500px;
background: var(--red);
border-radius: 50%;
-webkit-clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
z-index: 3;
border: 12px solid var(--black);
}
?
clip-path
clip-path
使用裁剪方式建立元素的可顯示區域。區域內的部分顯示,區域外的隱藏。
語法:
// 關鍵字 值
// none
clip-path: none;
// <clip-source> 值
clip-path: url(resources.svg#c1);
// <geometry-box> 值
clip-path: margin-box;
clip-path: border-box;
clip-path: padding-box;
clip-path: content-box;
clip-path: fill-box;
clip-path: stroke-box;
clip-path: view-box;
// <basic-shape> 值
clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: ellipse(50px 60px at 0 10% 20%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: path('M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z');
// 盒模型和形狀值結合
clip-path: padding-box circle(50px at 0 100px);
// 全域性值
clip-path: inherit;
clip-path: initial;
clip-path: revert;
clip-path: revert-layer;
clip-path: unset;
<clip-source>
:用url()
引用SVG
的<clipPath>
元素<basic-shape>
:一種形狀,其大小和位置由<geometry-box>
的值定義。如果沒有指定<geometry-box>
,則將使用border-box
用為參考框。取值可為以下值中的任意一個:inset()
:定義一個inset
矩形。circle()
:定義一個圓形,使用一個半徑和一個圓心位置。ellipse()
:定義一個橢圓,使用兩個半徑和一個圓心位置。polygon()
:定義一個多邊形,使用一個SVG
填充規則和一組頂點。path()
:定義一個任意形狀,使用一個可選的SVG
填充規則和一個SVG
路徑定義。
<geometry-box>
:如果同<basic-shape>
一起宣告,它將為基本形狀提供相應的參考框盒。通過自定義,它將利用確定的盒子邊緣包括任何形狀邊角(如被border-radius
定義的剪下路徑)。幾何框盒的可選值:margin-box
:margin box
作為引用框。border-box
:border box
作為引用框。padding-box
:padding box
作為引用框。content-box
:content box
作為引用框。fill-box
:利用物件邊界框object bounding box
作為引用框。stroke-box
:使用筆觸邊界框stroke bounding box
作為引用框。view-box
:使用最近的SVG
視口viewport
作為引用框。如果viewBox
屬性被指定來為元素建立SVG
視口,引用框將會被定位在座標系的原點,引用框位於由viewBox
屬性建立的座標系的原點,引用框的尺寸用來設定viewBox
屬性的寬高值。
none
:不建立剪下路徑。
步驟3:重疊部分優化 ??
將重疊部分設定為與第二個圓 ?
相同的漸變色,可以產生由第一圓 ?
過渡為第二圓 ?
的錯覺。
.cycle_2::before {
background: linear-gradient(to right, var(--red), var(--blue));
}
步驟4:文字 ?
Logo
文字是從左到右由藍到紅的漸變效果,可以通過將文字的盒背景設定為漸變色,然後通過 background-clip: text
將背景被裁剪成文字的前景色來實現。
<h1 class="text">聲生不息</h1>
.text {
background: linear-gradient(to right, var(--blue), var(--red));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
font-style: italic;
}
?
background-clip
background-clip
設定元素的背景圖片或顏色是否延伸到邊框、內邊距盒子、內容盒子下面。如果沒有設定background-image
或 background-color
,那麼這個屬性只有在 border
被設定為非 soild
、透明或半透明時才能看到視覺效果,否則本屬性產生的樣式變化會被邊框覆蓋。
語法:
// 關鍵字 值
background-clip: border-box;
background-clip: padding-box;
background-clip: content-box;
background-clip: text;
// 全域性值
background-clip: inherit;
background-clip: initial;
background-clip: unset;
border-box
:背景延伸至邊框外沿,但是在邊框下層。padding-box
:背景延伸至內邊距padding
外沿。不會繪製到邊框處。content-box
:背景被裁剪至內容區content box
外沿。text
:背景被裁剪成文字的前景色(實驗性屬性)。
步驟5:點選切換效果 ?
點選右上角的的半圓形圖案 ⌒
,可以實現將 Logo
從彩色切換為純白色,該功能是通過切換定義在 :root
下的 CSS變數
值實現的,可以通過以下方法實現 CSS變數
值的切換。
<span class="toggle" id="toggle" title="點選切換顏色"></span>
半圓形圖案 ⌒
的噪點背景效果是通過新增一張噪點圖實現。
.toggle {
background: linear-gradient(to left bottom, var(--blue), rgba(0, 0, 0, 0)), url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAAADFBMVEUvLy9eXl6AgICoqKhWH7o7AAAABHRSTlMSEhIS3WyPCwAAA1hJREFUOMsN0M3rDHEcwPH3d3y/4zcr67s1s3bIU62y8nBxcVCf79pZ4WBWsx6TVbvyEKUolJrxmBTj4SecVqE4OTjgIP6D5eC8DkouOJAj19fxhXJCWn811mk1Sp1q0J0q6AoNF7ZQ0uD+74CBj3otoUUEmJc0wqVEr2Ulatp1/6HYA9SGwfn+s6ftD8zsbic1idsPVrfcoQRYSrvbd7PdA7TY6cKcbfrwRXaJaqgTXSfDKd625S7XGB1YraJ0yuatOJmJvf5aqIwYINvBGIr+gZiDl80Qdoh3M1GTfuCzf1+yEetme3loJ3Hf6yijG5S9rRa7XI7Nzu1AYGF5Bd1cNeplTmN8yJpV8kYrpKEIAzXDgbBK2QhhTb37NP4P1aqRZ3ua6DVLb2AKjVpgBkbHie4QGFVqxDcpgL4tlTUMNKKgazpmWC+CkBBkTu59dpl+XikMg+U5izd/9z+KpxcFYvxxs01Vtho32XLZBNRmy8YWQBszOV6ES9r7cvQdshRbKVdfOrDKeyB+MeXsWvMmI95/Pdsp7J5MydZHR9MonithyhIllnSppjGaQRkb7vVyTaqNhLUsVI5I/HEDi3JYWdu+KEgsmkzJXGPZ97wQyqPREfp+vmAvzo3AfhF9HvZS1SiZL9H4pVgfhmofCltJ3wxq9/961Aaqq3HpzsFroqtPe9SVm3Ol5yd3f99TueB46l+9lB/drm4PxXs/4j4j5k6pAzS88njnDp72JijRYlYFRMaxfY8q20pWZjGLdKsCP2YoVYXl9RK1Kp7Xpx8MLYEe+gIWlUDwJNABR0AVAGQ4rfcCrci5YQYZonhi9ckLVrkTeCTeL5+0H7+Lw1baYjGu+6ddepc6qeLc8EhvL3dvf5Xi9maHyrGnCmFXXo7bk83O3C6FFYVDURtfLD4YVUpO011EfYvktpukxpKogevhPViJPC6tmWnOcxkaJYnwOw2zyoYKeAmKIlfpILLxBmOo3yLlkzh5+yTKmkvtrsc3oP8Tx7t8YTms2Be9a0TJNJ21Gb6k5mwY9Vn/P2vRSHu7tiZ2kx6mrMtCoqPG+9w3YWxOw5EZDcszz+tUQhZlq8j8Rw77ynqzi7XaV3kH8x62ScfWdhZpkgX3wWdZcibtbFASgOEfZmfZzbdc/O0AAAAASUVORK5CYII=');
}
// 獲取根元素
const root = document.querySelector(':root');
// 建立獲取變數值的函式
const getCssVariable = (key) => {
return getComputedStyle(root).getPropertyValue(key);
}
// 建立設定變數值的函式
const setCssVariable = (key, value) => {
root.style.setProperty(key, value);
}
// 點選切換CSS變數值
document.getElementById('toggle').addEventListener('click', () => {
if (getCssVariable('--blue') === '#FFFFFF') {
setCssVariable('--blue', '#0A68DF');
setCssVariable('--red', '#F66036');
} else {
setCssVariable('--blue', '#FFFFFF');
setCssVariable('--red', '#FFFFFF');
}
}, false);
?
Window.getComputedStyle()
Window.getComputedStyle()
方法返回一個物件,該物件在應用 active
樣式表並解析這些值可能包含的任何基本計算後,返回元素的所有 CSS
屬性的值。
語法:
let style = window.getComputedStyle(element, [pseudoElt]);
引數:
element
:用於獲取計算樣式的Element
。pseudoElt
:可選,指定一個要匹配的偽元素的字串。必須對普通元素省略或null
。
- 返回值:返回的
style
是一個實時的CSSStyleDeclaration
物件,當元素的樣式更改時,它會自動更新。
?
getComputedStyle
可以從偽元素拉取樣式資訊,如::after
,::before
,::marker
,::line-marker
。
?
CSSStyleDeclaration.getPropertyValue()
CSSStyleDeclaration.getPropertyValue()
介面返回一個 DOMString
,其中包含請求的 CSS
屬性的值。
語法:
var value = style.getPropertyValue(property);
- 引數:
property
是一個DOMString
,是需要查詢的CSS
屬性名稱。 - 返回值:
value
是DOMString
,包含查詢屬性的值。若對應屬性沒有設定,則返回空字串。
步驟6:噪點背景 ⬛
仔細觀察的話,頁面背景並不是單純的黑色,而是會有輕微的類似電視機 ?
雪花 ❄
的噪點效果,通過以下樣式即可實現噪點效果。
<div class="bg"></div>
背景是一張噪點圖片,設定背景時將 background-repeat
設定為 repeat
並新增通過translate
實現位移的動畫實現噪點晃動效果。
.bg {
position: fixed;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
width: 200%;
height: 200vh;
background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAgMAAADXB5lNAAAADFBMVEUvLy9eXl6AgICoqKhWH7o7AAAABHRSTlMSEhIS3WyPCwAAA1hJREFUOMsN0M3rDHEcwPH3d3y/4zcr67s1s3bIU62y8nBxcVCf79pZ4WBWsx6TVbvyEKUolJrxmBTj4SecVqE4OTjgIP6D5eC8DkouOJAj19fxhXJCWn811mk1Sp1q0J0q6AoNF7ZQ0uD+74CBj3otoUUEmJc0wqVEr2Ulatp1/6HYA9SGwfn+s6ftD8zsbic1idsPVrfcoQRYSrvbd7PdA7TY6cKcbfrwRXaJaqgTXSfDKd625S7XGB1YraJ0yuatOJmJvf5aqIwYINvBGIr+gZiDl80Qdoh3M1GTfuCzf1+yEetme3loJ3Hf6yijG5S9rRa7XI7Nzu1AYGF5Bd1cNeplTmN8yJpV8kYrpKEIAzXDgbBK2QhhTb37NP4P1aqRZ3ua6DVLb2AKjVpgBkbHie4QGFVqxDcpgL4tlTUMNKKgazpmWC+CkBBkTu59dpl+XikMg+U5izd/9z+KpxcFYvxxs01Vtho32XLZBNRmy8YWQBszOV6ES9r7cvQdshRbKVdfOrDKeyB+MeXsWvMmI95/Pdsp7J5MydZHR9MonithyhIllnSppjGaQRkb7vVyTaqNhLUsVI5I/HEDi3JYWdu+KEgsmkzJXGPZ97wQyqPREfp+vmAvzo3AfhF9HvZS1SiZL9H4pVgfhmofCltJ3wxq9/961Aaqq3HpzsFroqtPe9SVm3Ol5yd3f99TueB46l+9lB/drm4PxXs/4j4j5k6pAzS88njnDp72JijRYlYFRMaxfY8q20pWZjGLdKsCP2YoVYXl9RK1Kp7Xpx8MLYEe+gIWlUDwJNABR0AVAGQ4rfcCrci5YQYZonhi9ckLVrkTeCTeL5+0H7+Lw1baYjGu+6ddepc6qeLc8EhvL3dvf5Xi9maHyrGnCmFXXo7bk83O3C6FFYVDURtfLD4YVUpO011EfYvktpukxpKogevhPViJPC6tmWnOcxkaJYnwOw2zyoYKeAmKIlfpILLxBmOo3yLlkzh5+yTKmkvtrsc3oP8Tx7t8YTms2Be9a0TJNJ21Gb6k5mwY9Vn/P2vRSHu7tiZ2kx6mrMtCoqPG+9w3YWxOw5EZDcszz+tUQhZlq8j8Rw77ynqzi7XaV3kH8x62ScfWdhZpkgX3wWdZcibtbFASgOEfZmfZzbdc/O0AAAAASUVORK5CYII=') repeat 0 0;
background-repeat: repeat;
animation: bg-animation .2s infinite;
}
@keyframes bg-animation {
0% { transform: translate(0,0) }
10% { transform: translate(-5%,-5%) }
// ...
100% { transform: translate(5%,0) }
}
完整程式碼:https://github.com/dragonir/s...
總結
本文包含的知識點主要包括:
repeating-linear-gradient
條紋背景clip-path
形狀裁切background-clip
設定元素的背景延伸Window.getComputedStyle()
獲取計算後元素的所有CSS
屬性的值CSSStyleDeclaration.getPropertyValue()
獲取請求的CSS
屬性的值
想了解其他前端知識或 WEB 3D
開發技術相關知識,可閱讀我往期文章。轉載請註明原文地址和作者。如果覺得文章對你有幫助,不要忘了一鍵三連哦 ?。
附錄
- [1]. ? 前端實現很哇塞的瀏覽器端掃碼功能
- [2]. ? 前端瓦片地圖載入之塞爾達傳說曠野之息
- [3]. ? 僅用CSS幾步實現賽博朋克2077風格視覺效果
...
- [1]. ? Three.js 實現3D開放世界小遊戲:阿狸的多元宇宙
- [2]. ? Three.js 火焰效果實現艾爾登法環動態logo
- [3]. ? Three.js 實現2022冬奧主題3D趣味頁面,含冰墩墩
...