有趣的css知識又增長了之 conic-gradient + 餅圖組件

本文由團隊成員 BingLee1994 撰寫,已受權塗鴉大前端獨家使用,包括但不限於編輯、標註原創等權益。javascript

你是否是有這種感受:能用幾行css畫出來,不用四處找svg或者上傳圖片,就以爲特別開心呢。那麼漸變就能夠作不少這樣的事情,好比花紋,遮罩,常見圖形等。css

咱們熟知的有線性漸變和錐形漸變,那麼今天介紹另外一位夥伴 conic-gradient 錐形漸變。html

兼容性

主流現代瀏覽器均兼容。 581db541-7a14-4a20-9e89-f34392436bb9-image.png前端

全部好玩高效的css特性均不兼容IE11,不要讓他成爲阻礙進步的絆腳石。java

名詞解釋

若是你初次接觸漸變呢,簡單瞭解下:漸變由方向位置,和多個顏色駐點組成。git

顏色駐點

一個顏色駐點由顏色和位置組成,用空格隔開,如下圖爲例: 708ba743-df40-4cf3-a94b-1556739422cd-image.png 能夠看到背景由綠→紅→藍,控制顏色的圈圈就是顏色駐點,那麼本圖中綠和藍分別在頭尾部,紅色在25%的位置,那麼這個紅色駐點表示爲:red 25%,處於頭尾部可沒必要寫位置。github

方向與中心

上圖咱們明顯看到漸變朝右,那麼咱們能夠指定漸變的方向爲任意角度,以下面這樣 eda8cca0-8201-49ea-840e-9aba2491ef38-image.png 特殊的,錐形漸變和放射漸變還能夠指定中心點,放射漸變還能夠指定半徑,原型橢圓形等。 95979704-00ea-4be5-a34d-424d7de16a2c-image.png瀏覽器

conic-gradient

好,進入正題,什麼是conic-gradient(錐形漸變)?顧名思義,看下圖 f33c7c4a-ca33-4d95-bed8-8b99f1a7b708-image.png 發現了嗎?顏色繞着中心點旋轉了一週,就像圓錐同樣,這就是錐形漸變,顏色駐點位置以下圖紅線所示,恰好在半徑線上: 4b26b7b2-4877-4d4a-99bd-247277b49b7f-image.pngmarkdown

語法

backgrouns-image: conic-gradient([ 角度 [at 位置] ], 顏色駐點1, 顏色駐點2, 顏色駐點...) 其中中括號表示非必要屬性,默認角度爲0,位置在元素正中心,大部分場景,默認的就知足需求。
顏色駐點位置除了可使用百分比,還可使用角度表示法。dom

試一試

語法看着有點長,別懼怕,讓咱們寫一個css試試效果吧:

div {
  width: 200px;
  height: 200px;
  background-image: conic-gradient(orange, blue 50%, purple)
}
複製代碼

渲染以下:沿着中心轉一圈,開始由橙色轉到50%變爲藍色,而後由藍色轉到360°變成紫色,就是這麼簡單!

那麼上述50%還可使用角度表示法: conic-gradient(orange, blue 180deg, purple), 特別地,能夠指定兩個角度,表示顏色覆蓋的角度區域,好比 conic-gradient(orange, blue 180deg 240deg, purple).

c8f11dab-05bf-4165-985e-c86d675664ee-image.png

開始畫餅圖

光了解而不會實際應用怎麼能夠呢?本文咱們拿常見的餅圖爲實際應用案例,來更進一步體驗錐形漸變。

以下圖:橙色區域佔30%. 4df6b5d9-e373-49f7-900c-9b1ae310c18a-image.png

差在哪裏?

對比下咱們上述漸變和這個餅圖差在哪裏呢?
沒錯,你發現了嗎?餅圖背景和橙色扇形區域(下文咱們叫進度)之間的銜接處是硬的而不是漸變過渡的。 d6a59dfa-95bf-4942-9589-941a0339fc8d-image.png 怎麼作呢?不要着急,讓咱們先把漸變畫出來:

div {
  width: 200px;
  height: 200px;
  background-image: conic-gradient(orange, purple 30%)
}
複製代碼

e58cc51d-5e97-4509-b2bf-8c31e7c34592-image.png

讓顏色銜接處變硬

唉~,咱們驚喜發現,在起始處0°和360°,是一條橙色直接到紫色的硬線,而不是漸變,由於0° = 360 °,同一個角度位置出現兩種顏色,那麼兩個顏色距離是0,換句話說,留給橙色漸變到紫色的空間長度爲0,那天然視覺上就是沒有漸變,相連處變硬,顏色直接改變

知道了這個道理,咱們就能夠輕鬆畫出上述餅圖,只須要將上述30%的位置添加兩個顏色駐點,這樣他們兩個就會直接硬性過渡。

讓咱們修改css代碼以下:

div {
  width: 200px;
  height: 200px;
  background-image: conic-gradient(orange 30%, purple 30%);
  /* 30%的位置設置兩個駐點橙色和紫色,那麼在這個位置直接硬性過渡而無漸變 */
}
複製代碼

d9c15801-eceb-4187-bc8a-84144e83be81-image.png 大功告成,最後不要忘了加個border-radius,so easy!

餅圖動起來

這麼有趣的東西咱們確定要封裝成組件用才能用到真實的場景,上文咱們輕鬆畫出了30%的餅圖,相似地,經過更改百分比就可讓餅圖動起來了,那麼咱們寫個簡單地demo控制餅圖,咱們經過一個滑塊控制!

你能夠直接拷貝以下html代碼作練習

<body>
  <style> body { height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; } #pie-chart { width: 200px; height: 200px; border-radius: 100px; background-image: conic-gradient(orange 0%, purple 0%); margin-bottom: 24px; } </style>

  <div id="pie-chart"></div>
  <input id="slider" type="range" value="0" max="100" min="0" step="10" />

  <script type="text/javascript"> // js代碼寫這裏 </script>
</body>
複製代碼

6ceb40ce-5ad5-46cf-ac8b-74f5acbbe2d8-image.png

添加滑塊事件

本例中滑塊取值爲0 ~ 100,對應顏色駐點位置,經過添加滑塊的input事件來控制餅圖百分比:

<script type="text/javascript"> const elPieChart = document.getElementById('pie-chart') const elSlider = document.getElementById('slider') elSlider.oninput = function updateChart() { const { value } = elSlider //將滑塊value轉換爲駐點位置 elPieChart.style.backgroundImage = `conic-gradient(orange ${value}%, purple ${value}%)` } </script>
複製代碼

你看,就是這麼短短几句代碼,餅圖就能動起來了😊! 230c6ade-b5fe-47dd-813d-10ce571a7991-屏幕錄製2021-06-05 上午10.43.44.gif

組件可定製

上面紫色餅可能不合你口味,讓咱們在js代碼裏換換顏色吧,咱們定義兩個變量,一個背景色,一個進度顏色,最後修改css背景便可:

<script type="text/javascript"> // 自定義顏色 const chartColor = '#C6E9FF' const chartProgressColor = '#4589EF' const elPieChart = document.getElementById('pie-chart') const elSlider = document.getElementById('slider') // 首次渲染設置顏色 elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} 0%, ${chartColor} 0%)` elSlider.oninput = function updateChart() { const { value } = elSlider //更改餅圖進度 elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} ${value}%, ${chartColor} ${value}%)` } </script>
複製代碼

a1d95f3a-1076-468e-8eb8-f4d18f049dec-image.png

持續優化

你覺得寫到這裏就結束了嗎?讓咱們回過頭看看代碼,只是增長了個顏色需求,js代碼開始變得很是醜陋,主要出如今 elPieChart.style.backgroundImage = `conic-gradient(${chartProgressColor} ${value * 100}%, ${chartColor} ${value * 100}%)

這一坨代碼很是刺眼,由於:

  1. 這個css字符串很臭長。
  2. js拼接css字符串由於沒有代碼提示,因此很是容易寫錯,中間少個標點符號空格啥的,調試起來太噁心了。
  3. 今天我寫的,我能看懂,過幾天我再來看,我本身都看不懂了,無可維護性!

若是你在平常組件開發時遇到相似的煩惱,那麼好消息是,這是一個典型的使用css變量的應用場景教程傳送門

代碼可維護性在整個項目中很是重要,不要爲了趕進度或者偷懶而忽視。

使用css變量瘦身

如今,讓咱們把全部樣式有關的東西統統留在css代碼裏,本例中是兩個顏色和一個餅圖進度,那麼相應的,咱們要暴露出對應的css變量讓js來操做。是的,css代碼就應該老老實實呆在css裏面,不要出來湊熱鬧.

修改上面的css代碼以下,定義須要暴露給js的變量並賦予初始值:

#pie-chart {
  /* 聲明變量並初始化 */
  --chartColor: orange; /* 背景色 */
  --chartProgressColor: purple; /* 進度色 */
  --chartProgress: 0%; /* 進度 */

  width: 200px;
  height: 200px;
  border-radius: 100px;
  /* 使用變量,(有點模板的意思) */
  background-image: conic-gradient(
    var(--chartProgressColor) var(--chartProgress), 
    var(--chartColor) var(--chartProgress)
  );
  margin-bottom: 24px;
}
複製代碼

而後在js裏直接操做css變量便可,API傳送門

<script type="text/javascript"> // 自定義顏色 const chartColor = '#C6E9FF' const chartProgressColor = '#4589EF' const elPieChart = document.getElementById('pie-chart') const { style } = elPieChart const elSlider = document.getElementById('slider') // 首次渲染設置顏色 style.setProperty('--chartColor', chartColor) style.setProperty('--chartProgressColor', chartProgressColor) elSlider.oninput = function updateChart() { const { value } = elSlider //更改餅圖進度 style.setProperty('--chartColor', chartColor) style.setProperty('--chartProgressColor', chartProgressColor) style.setProperty('--chartProgress', `${value}%`) } </script>
複製代碼

如今咱們用更優,可讀性更高的變量代替傳統css拼接字符串,通過優化後的js代碼更加js.

你能夠用喜歡的方式繼續重構,那麼上述操做css變量的部分其實能夠再優化,能夠寫工具類,可是不管如何,終於擺脫了css.

試想,若是咱們的組件dom層級很深,還按照老的笨方法,層層查找節點,樣式穿透,將會是噩夢,使用css變量,只需專一變量自身,而無需考慮dom層級,而且開發者能夠更好維護,也方便了使用者經過css hack的手段去定製樣式,但願你能get到這個點。

更多場景

除了餅圖,圓環進度條,Loading動畫,遮罩等等也是錐形漸變的使用場景,大膽發揮你的想象力吧。

喜歡本文記得三連支持😙

相關文章
相關標籤/搜索