按下右側的「點擊預覽」按鈕能夠在當前頁面預覽,點擊連接能夠全屏預覽。css
https://codepen.io/comehope/pen/rgmPLRhtml
此視頻是能夠交互的,你能夠隨時暫停視頻,編輯視頻中的代碼。前端
請用 chrome, safari, edge 打開觀看。git
https://scrimba.com/p/pEgDAM/c2LBPPtggithub
每日前端實戰系列的所有源代碼請從 github 下載:chrome
https://github.com/comehope/front-end-daily-challenges瀏覽器
Safari 瀏覽器的 LOGO 是一個指南針的形狀,它的主要元素有 2 個,一個是圍繞在錶盤周圍的刻度線,一個是中間的指針。因此咱們定義 dom 結構以下,其中 .marks
表明刻度線,.pointer
表明指針。.marks
中有 4 個 <span>
元素,它們表明刻度線,實際的刻度線有幾十條,這裏只定義 4 條,目的是便於書寫樣式,等樣式寫好後,接下來會用 JavaScript 批量生成刻度線:app
<figure class="safari"> <div class="marks"> <span></span> <span></span> <span></span> <span></span> </div> <div class="pointer"></div> </figure>
讓做品顯示在頁面正中,頁面背景爲黑色:dom
body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: black; }
LOGO 容器是一個白色的圓角正方形。做品將使用 em
做爲長度單位,若是想修改 LOGO 的尺寸,只要修改這裏的 font-size
屬性就能夠了。用 flex
佈局令其中的子元素 .marks
和 .pointer
都居中顯示:函數
.safari { font-size: 10px; width: 15em; height: 15em; background-color: snow; border-radius: 25%; padding: 1em; display: flex; align-items: center; justify-content: center; }
先繪製出刻度線所在的錶盤,用線性漸變填充上藍色漸變色:
.marks { width: inherit; height: inherit; background-image: linear-gradient( hsl(191, 98%, 55%), hsl(220, 88%, 53%) ); border-radius: 50%; }
再繪製出刻度線。圍繞着一個圓周繪圖的技巧是先令一組元素逐個旋轉較小的角度(用 rotate()
函數實現),再讓這些元素向旋轉的方向移動(用 translate()
函數實現)。這裏用變量 --rotate-deg
存儲旋轉的角度:
.marks { display: flex; align-items: center; justify-content: center; } .marks span { position: absolute; width: 0.1em; height: 0.9em; background-color: snow; transform: rotate(var(--rotate-deg)) translateY(6em); } .marks span:nth-child(1) {--rotate-deg: 0deg;} .marks span:nth-child(2) {--rotate-deg: 90deg;} .marks span:nth-child(3) {--rotate-deg: 180deg;} .marks span:nth-child(4) {--rotate-deg: 270deg;}
如今能夠看到 4 條刻度線分別定位到錶盤的上、下、左、右的邊緣位置了。
由於刻度線有不少條,爲了減小代碼量,咱們用 JavaScript 來批量建立刻度線。
在此以前,先刪除掉 html 中的聲明 <span>
元素的 4 行代碼:
<figure class="safari"> <div class="marks"> <!-- <span></span> <span></span> <span></span> <span></span> --> </div> <div class="pointer"></div> </figure>
再刪除 css 中設置刻度線角度的代碼:
/* .marks span:nth-child(1) {--rotate-deg: 0deg;} .marks span:nth-child(2) {--rotate-deg: 90deg;} .marks span:nth-child(3) {--rotate-deg: 180deg;} .marks span:nth-child(4) {--rotate-deg: 270deg;} */
而後用 js 來批量建立 60 條刻度線:
const MARKS_COUNT = 60 Array(MARKS_COUNT).fill('').forEach((x, i) => { let span = document.createElement('span') span.style.setProperty('--rotate-deg', i * 360 / MARKS_COUNT + 'deg') document.querySelector('.marks').appendChild(span) })
這裏稍複雜的是表達式 i * 360 / MARKS_COUNT + 'deg'
,其中 360 / MARKS_COUNT
是把一個圓周的 360 度分紅若干份(也就是刻度線數量那麼多的份數)以後每一份的角度,再用每一份的下標值 i
去乘它,就獲得每條刻度線應旋轉的角度了。
接下來設置刻度線的細節,令刻度線長短交錯。表明刻度線長度的變量是 --h
,長線長 0.9em
,短線長 0.5em
,爲了讓刻度線對齊,再用變量 --y
存儲偏移量,令長線偏移 6em
,短線偏移 6.2em
。同時修改 height
屬性和 translateY()
函數,讓它們引用這 2 個變量的值。由於刻度線長短交錯,因此用 :nth-child(odd)
和 :nth-child(even)
來設置 2 組不一樣的參數值:
.marks span { height: var(--h); transform: rotate(var(--rotate-deg)) translateY(var(--y)); } .marks span:nth-child(odd) {--h: 0.9em; --y: 6em;} .marks span:nth-child(even) {--h: 0.5em; --y: 6.2em;}
至此,刻度線繪製完成。
指針是由 2 個三角形組成的,對於這種成對的元素,一般都用僞元素繪製。先肯定一下指針的尺寸,用 flex
令它的子元素(也就是 2 個僞元素)縱向排列:
.pointer { position: absolute; width: 1.4em; height: 12em; display: flex; flex-direction: column; }
繪製三角形的技巧是令容器的尺寸爲 0
寬 0
高,而後用 3 條邊框構成三角形,要是看不懂這段代碼的話,動手試試就明白了。這裏也定義了一個變量 --c
,用於存儲 2 個三角形的顏色,分別是紅色和白色:
.pointer::before, .pointer::after { content: ''; border-bottom: 6em solid var(--c); border-left: 0.7em solid transparent; border-right: 0.7em solid transparent; } .pointer::after { transform: rotate(180deg); } .pointer::before {--c: crimson;} .pointer::after {--c: snow;}
到這裏,指針繪製完成,整個 LOGO 的形狀也已經完成了。
最後,加一點動畫效果,讓指針像指南針那樣轉動。原理很簡單,就是讓指針在 30
度到 50
度之間來回擺動:
.pointer { transform: rotate(30deg); animation: rotate 1s ease-in-out infinite alternate; } @keyframes rotate { to { transform: rotate(50deg); } }
大功告成!