最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

用CSS+SVG做一個(gè)優(yōu)雅的環(huán)形進(jìn)度條

2023-10-19 10:46 作者:OpenTiny社區(qū)  | 我要投稿

開門見山

先上最終效果圖:(Demo 傳送門)

其中進(jìn)度、尺寸、環(huán)寬和顏色都可以非常方便地進(jìn)行控制。

核心原理:

利用兩個(gè)重疊的圓環(huán)形,通過(guò)對(duì)上層圓環(huán)弧長(zhǎng)的控制來(lái)表示進(jìn)度,下層圓環(huán)則作為輔助,呈現(xiàn)環(huán)形進(jìn)度條剩余的部分。

核心知識(shí)點(diǎn):

  • SVG circle?stroke-dasharray

  • 弧長(zhǎng)公式?l = πrα/180°

  • CSS 變量

  • CSS 計(jì)數(shù)器

下面分享下具體實(shí)現(xiàn)過(guò)程。

實(shí)現(xiàn)環(huán)形

要實(shí)現(xiàn)環(huán)形,有多種技術(shù)可供選擇,包括 Canvas、SVG,甚至 CSS + HTML 的組合。在本文中,我們使用了 SVG 方案,一來(lái)是因?yàn)?SVG 的 API 豐富,圖形表現(xiàn)力非常強(qiáng)大,二來(lái)是 SVG 可以與 CSS 無(wú)縫搭配使用,實(shí)現(xiàn)更加強(qiáng)大的功能。

用 SVG 中的 circle 標(biāo)簽可以毫無(wú)壓力的繪出一個(gè)直徑 200px 的圓環(huán):

我們?cè)僬{(diào)整下代碼,讓圓環(huán)圖形完美適應(yīng) SVG 容器的 200×200 大?。?/p>


小技巧:為了完美適應(yīng)容器尺寸,我們可以將半徑?r?的值設(shè)置為容器寬度的一半減去?stroke-width?大小的一半,這樣做可以確保圓環(huán)不會(huì)因?yàn)橐绯龆蝗萜骷舨玫簟4颂?r = 200 / 2 - 10 / 2,即 (200 - 10) / 2 = 95

接著使用相同的方法繪制另一個(gè)圓環(huán),作為輔助圓環(huán)。為了視覺效果,進(jìn)度圓環(huán)應(yīng)該在上層,因此在代碼中,進(jìn)度圓環(huán)的標(biāo)簽應(yīng)該放在輔助圓環(huán)的后面。完成后的代碼如下:

可以發(fā)現(xiàn)代碼中有很多重復(fù)的屬性,為了讓代碼更加簡(jiǎn)潔和高效,我們可以使用 CSS 將這些重復(fù)的部分提取出來(lái),統(tǒng)一聲明,讓代碼變得更加“干”(DRY):

實(shí)現(xiàn)圓環(huán)進(jìn)度

上下兩層的圓環(huán)已經(jīng)準(zhǔn)備好了,現(xiàn)在的重點(diǎn)是如何實(shí)現(xiàn)上層圓環(huán)上的進(jìn)度,這個(gè)問(wèn)題可以分為2個(gè)關(guān)鍵點(diǎn):

  1. 如何實(shí)現(xiàn)圓環(huán)的弧長(zhǎng)?

  2. 如何將進(jìn)度百分比轉(zhuǎn)換為圓環(huán)的弧長(zhǎng)?

要解決第1個(gè)問(wèn)題,這里要用到 SVG 中的?stroke-dasharray?屬性,這是一個(gè)用來(lái)控制路徑虛線疏密程度的屬性,其值是一組描述虛線的短劃線與空白間隙長(zhǎng)度的數(shù)列。例如,如果設(shè)置?stroke-dasharray="5 2",則路徑將以 5 個(gè)像素的短劃線和 2 個(gè)像素的空白間隙交替顯示,其中第一個(gè)數(shù)控制短劃線長(zhǎng)度,第二個(gè)數(shù)控制空白間隙長(zhǎng)度。

stroke-dasharray?的參數(shù)值還支持多個(gè)數(shù)列,詳情見?MDN 文檔

很明顯,這里我們需要控制圓弧的長(zhǎng)度(即虛線中的短劃線長(zhǎng)度)來(lái)呈現(xiàn)進(jìn)度。然而,由于虛線中的短劃線是多個(gè)且重復(fù)的,僅僅改變短劃線長(zhǎng)度并不能滿足我們的需求,具體情況如下圖所示:

根據(jù)需求,我們只需要圓環(huán)的?一段?圓弧即可,那如何實(shí)現(xiàn)呢?經(jīng)過(guò)多次嘗試,我們發(fā)現(xiàn)當(dāng)改變虛線中空白間隙的長(zhǎng)度(即?stroke-dasharray?的第二個(gè)數(shù)),當(dāng)這個(gè)長(zhǎng)度超過(guò)圓環(huán)的周長(zhǎng)時(shí),視覺效果上圓環(huán)只剩下一條獨(dú)立的圓弧了,此時(shí)我們可以通過(guò)調(diào)整第一個(gè)數(shù)來(lái)改變圓弧的長(zhǎng)度,從而解決了上面第1個(gè)問(wèn)題。

上面第2個(gè)問(wèn)題暫時(shí)看起來(lái)比較棘手,因?yàn)槲覀兒茈y看出0%~100%之間的進(jìn)度到底對(duì)應(yīng)多長(zhǎng)的弧長(zhǎng)。我們繼續(xù)探究,尋找規(guī)律。

根據(jù)需求,當(dāng)進(jìn)度百分比是100%時(shí),進(jìn)度條的圓弧要呈現(xiàn)出一個(gè)圓環(huán),此時(shí)圓弧夾角是360°,當(dāng)進(jìn)度百分比是50%時(shí),圓弧是個(gè)半圓環(huán),夾角是180° 。反過(guò)來(lái)也成立:180°表示50%,360°表示100% ??梢钥闯鲞M(jìn)度百分比和角度是存在等量關(guān)系的,同時(shí)根據(jù)弧長(zhǎng)公式?l = πrα/180°,帶入角度就可以求出弧長(zhǎng)了,至此“進(jìn)度百分比 - 角度 - 弧長(zhǎng)”三者的規(guī)律就清晰了,思路馬上要通了。

l = πrα/180°

其中?l?表示弧長(zhǎng),π?是圓周率,r?表示半徑,α?表示夾角

在實(shí)際使用中,我們是用百分?jǐn)?shù)來(lái)控制弧長(zhǎng)的,而不是用角度,所以接下來(lái)把進(jìn)度百分比和弧長(zhǎng)關(guān)聯(lián)起來(lái)。

我們把弧長(zhǎng)公式變動(dòng)下,分子分母同時(shí)乘以2,則有:

l = 2πrα/180°*2,即?l = 2πr * α/360°

同時(shí)根據(jù)前面可知進(jìn)度百分比和角度存在等量關(guān)系(360° 等于 100%),所以可以得到:

l = 2πr * p/100,其中?p?為當(dāng)前進(jìn)度百分?jǐn)?shù)。

現(xiàn)在,我們就可以根據(jù)進(jìn)度百分比來(lái)計(jì)算出對(duì)應(yīng)的弧長(zhǎng)了。

優(yōu)化細(xì)節(jié)

環(huán)形進(jìn)度條通常都是從12點(diǎn)鐘方向開始的,而 SVG 中默認(rèn)是3點(diǎn)鐘方向作為起點(diǎn),所以我們給它偏轉(zhuǎn)-90°進(jìn)行修正:

另外我們發(fā)現(xiàn)圓弧的端點(diǎn)處過(guò)于生硬,給個(gè)圓角效果修飾下是個(gè)好主意。這里我們用了 SVG 中的屬性?stroke-linecap

當(dāng)然了,動(dòng)畫過(guò)渡效果也可以安排上,讓進(jìn)度條的變化更加絲滑:

組件化

環(huán)形進(jìn)度條的效果雖然已經(jīng)實(shí)現(xiàn)了,但光靠上面的那些代碼還是很難復(fù)用。環(huán)形進(jìn)度條的寬度、高度、半徑、顏色等都是寫死的,另外?stroke-dasharray?的值還得靠 JS 進(jìn)行計(jì)算,再賦值給?<circle>?元素。說(shuō)好的純 CSS 實(shí)現(xiàn)呢?

要解決這些問(wèn)題,我們需要將環(huán)形進(jìn)度條組件化。

先定義一些組件全局要用到的 CSS 變量:

然后利用?calc?將寫死的數(shù)值改為根據(jù) CSS 變量動(dòng)態(tài)計(jì)算:

SVG 中的?stroke-dasharray?也調(diào)整為根據(jù) CSS 變量動(dòng)態(tài)計(jì)算:

這樣我們通過(guò)改變父容器的?--percent?變量就能直接控制進(jìn)度條的百分比顯示了。

同理,也可以改變其他內(nèi)部變量來(lái)方便地控制組件的外觀和尺寸。例如可以根據(jù)閾值來(lái)動(dòng)態(tài)調(diào)整進(jìn)度條顏色:

顯示百分比文本

可以把百分比的文本顯示在環(huán)形進(jìn)度條的中央,增強(qiáng)可視化效果。有了前面的鋪墊,這里只需用偽元素 + CSS 計(jì)數(shù)器就能輕松實(shí)現(xiàn)百分比文本顯示。

由于 SVG 中不支持偽元素,所以我們加一層 HTML 標(biāo)簽作為主容器:

然后為主容器增加偽元素,居中定位,再利用 CSS 計(jì)數(shù)器接收?--percent?變量的值:

效果如下圖:

完善邊界場(chǎng)景

上面為圓環(huán)加了?stroke-linecap: round?讓描邊的端點(diǎn)圓角化,不過(guò)卻引出了一個(gè)小問(wèn)題:當(dāng)真實(shí)進(jìn)度為 0% 時(shí),由于端點(diǎn)圓角的存在,使得進(jìn)度條在視覺效果上明顯大于0%,正如下圖所示:

受《純CSS實(shí)現(xiàn)未讀消息超過(guò)100自動(dòng)顯示為99+》一文的啟發(fā),我們?yōu)檫M(jìn)度圓環(huán)加一個(gè)值為?--percent?的?opacity?屬性即可解決這個(gè)問(wèn)題:

當(dāng)?--percent?的值為 0 時(shí),此處?opacity?為 0,則進(jìn)度圓環(huán)完全透明不顯示;當(dāng)?--percent?的值大于 0 時(shí),opacity?的值按 1 處理,則進(jìn)度圓環(huán)正常顯示。

擴(kuò)展:儀表盤式進(jìn)度條

環(huán)形進(jìn)度條還有一種變體——儀表盤式進(jìn)度條,顧名思義就是以儀表盤的形態(tài)顯示進(jìn)度,有著視覺吸引力強(qiáng)和易于理解的優(yōu)點(diǎn)。下圖是來(lái)自?AntDesign?的儀表盤式進(jìn)度條示例:

在前面知識(shí)的基礎(chǔ)上,我們趁熱打鐵再做一個(gè)儀表盤式進(jìn)度條。

生成缺口

在視覺上,儀表盤式進(jìn)度條相比圓環(huán)進(jìn)度條最大的不同就是前者有個(gè)空白“缺口”,且缺口朝下,整體左右對(duì)稱。

我們很容易能夠想到用?stroke-dasharray?的第1個(gè)參數(shù)來(lái)生成可見的圓?。础叭笨凇币酝獾牟糠郑?,用第2個(gè)參數(shù)來(lái)生成間隙(即“缺口”)。以中心夾角90°的缺口為例,代入弧長(zhǎng)公式(l = πrα/180°)則有:

效果如下圖所示:

確定?svg?旋轉(zhuǎn)角度

在不對(duì)容器做任何旋轉(zhuǎn)的情況下,這個(gè)90°缺口朝向右上角,而我們實(shí)際想要的是讓缺口朝下,且整體左右對(duì)稱。要達(dá)到這個(gè)目的,我們需要將?svg?容器順時(shí)針旋轉(zhuǎn)135°,效果如下:

在實(shí)際場(chǎng)景中,這個(gè)“缺口”的大小是可配置的,所以我們把缺口夾角封裝到主容器的 CSS 變量里,方便后續(xù)的動(dòng)態(tài)計(jì)算。

當(dāng)缺口夾角變成動(dòng)態(tài)時(shí),svg?容器到底需要旋轉(zhuǎn)多少度才能使缺口的開口朝下,且整體左右對(duì)稱呢?我們接著以90°夾角的缺口為例來(lái)分析。從前面實(shí)踐可知想要讓90°缺口朝下,且整體左右對(duì)稱,則需要將?svg?容器順時(shí)針旋轉(zhuǎn)135°,旋轉(zhuǎn)后的示意圖如下:

其中?∠A = ∠B = 135°,仔細(xì)觀察可發(fā)現(xiàn),這里的135°等于缺口自身夾角90°加上 ∠A 與 ∠B 重合的夾角45°. 顯然,當(dāng)缺口夾角發(fā)生變化時(shí),此處的重合夾角需要?jiǎng)討B(tài)計(jì)算,結(jié)合上圖我們不難看出這里存在一個(gè)等式:

2 × 重合夾角 + 缺口夾角 = 180°

那么則有:

重合夾角 = (180° - 缺口夾角) / 2

結(jié)合 CSS 變量我們就可以確定?svg?容器的旋轉(zhuǎn)角度,代碼如下:

這樣我們的進(jìn)度條就能適配不同的缺口夾角了:

修正進(jìn)度換算

當(dāng)我們按環(huán)形進(jìn)度條的方式來(lái)測(cè)試儀表盤式進(jìn)度條時(shí),發(fā)現(xiàn)儀表盤式進(jìn)度條的進(jìn)度顯示有問(wèn)題——實(shí)際進(jìn)度百分比和進(jìn)度顯示不匹配,如下圖所示:

其實(shí)也不難理解,我們先看一下現(xiàn)有進(jìn)度圓環(huán)的代碼部分:

在圓環(huán)進(jìn)度條中,這里的?var(--percent) / 100?與?α / 360°?是等價(jià)的,360°圓弧表示100%進(jìn)度,但在儀表盤式進(jìn)度條中,360°減去缺口夾角后對(duì)應(yīng)的圓弧才真正表示100%進(jìn)度。所以我們得把缺口夾角的因素?fù)Q算進(jìn)去,修正實(shí)際的進(jìn)度顯示。

我們從這個(gè)公式入手:l = 2πr * α/360°

在圓環(huán)進(jìn)度條中,50%的進(jìn)度對(duì)應(yīng)180°的圓弧夾角,代入公式則有:

l = 2πr * 180 / 360

如換成儀表盤式進(jìn)度條,當(dāng)缺口夾角為90°時(shí),這里的分母就是?360° - 90° = 270°。小學(xué)數(shù)學(xué)教會(huì)我們:分子分母等比變化時(shí),其值不變,所以我們給分子也乘以分母變化的值,則有:

l = 2πr * 180 * (270 / 360) / 270

進(jìn)一步分解下可得:l = πr * 180 * (270 / 180) / 270

我們把除缺口夾角外的圓弧換成 CSS 變量?--active-degree: calc(360 - var(--gap-degree));,寫到進(jìn)度圓環(huán)的代碼中:

其中?(180 * var(--active-degree) / 180) / var(--active-degree)?等價(jià)于?(var(--percent) * var(--active-degree) / 180) / 100,答案已經(jīng)呼之欲出了:

最終效果:(Demo 傳送門)

最后

利用 CSS 和 SVG 技術(shù),我們成功地實(shí)現(xiàn)了一個(gè)優(yōu)雅的環(huán)形進(jìn)度條,這個(gè)進(jìn)度條不僅能夠展示進(jìn)度,還能夠通過(guò) CSS 變量來(lái)調(diào)整樣式滿足不同的需求。希望這篇分享對(duì)大家使用 CSS 和 SVG 有所幫助,也希望大家能夠在實(shí)踐中不斷探索和創(chuàng)新,做出更加實(shí)用和美觀的作品。

關(guān)于OpenTiny

OpenTiny 是一套企業(yè)級(jí) Web 前端開發(fā)解決方案,提供跨端、跨框架的UI組件庫(kù),適配 PC 端 / 移動(dòng)端等多端,支持 Vue2 / Vue3 / Angular 多技術(shù)棧,擁有靈活擴(kuò)展的低代碼引擎,包含主題配置系統(tǒng) / 中后臺(tái)模板 / CLI 命令行等豐富的效率提升工具,可幫助開發(fā)者高效開發(fā) Web 應(yīng)用。

核心亮點(diǎn):

  • 跨端跨框架:?使用 Renderless 無(wú)渲染組件設(shè)計(jì)架構(gòu),實(shí)現(xiàn)了一套代碼同時(shí)支持 Vue2 / Vue3,PC / Mobile 端,并支持函數(shù)級(jí)別的邏輯定制和全模板替換,靈活性好、二次開發(fā)能力強(qiáng)。

  • 組件豐富:PC 端有100+組件,移動(dòng)端有30+組件,包含高頻組件 Table、Tree、Select 等,內(nèi)置虛擬滾動(dòng),保證大數(shù)據(jù)場(chǎng)景下的流暢體驗(yàn),除了業(yè)界常見組件之外,我們還提供了一些獨(dú)有的特色組件,如:Split 面板分割器、IpAddress IP 地址輸入框、Calendar 日歷、Crop 圖片裁切等。

  • 低代碼引擎:低代碼引擎使能開發(fā)者定制低代碼平臺(tái)。它是低代碼平臺(tái)的底座,提供可視化搭建頁(yè)面等基礎(chǔ)能力,既可以通過(guò)線上搭配組合,也可以通過(guò)下載源碼進(jìn)行二次開發(fā),實(shí)時(shí)定制出自己的低代碼平臺(tái)。適用于多場(chǎng)景的低代碼平臺(tái)開發(fā),如:資源編排、服務(wù)端渲染、模型驅(qū)動(dòng)、移動(dòng)端、大屏端、頁(yè)面編排等。

  • 配置式組件:?組件支持模板式和配置式兩種使用方式,適合低代碼平臺(tái),目前團(tuán)隊(duì)已經(jīng)將 OpenTiny 集成到內(nèi)部的低代碼平臺(tái),針對(duì)低碼平臺(tái)做了大量?jī)?yōu)化。

  • 周邊生態(tài)齊全:?提供了基于 Angular + TypeScript 的 TinyNG 組件庫(kù),提供包含 10+ 實(shí)用功能、20+ 典型頁(yè)面的 TinyPro 中后臺(tái)模板,提供覆蓋前端開發(fā)全流程的 TinyCLI 工程化工具,提供強(qiáng)大的在線主題配置平臺(tái) TinyTheme。

歡迎加入 OpenTiny 開源社區(qū)。添加微信小助手:opentiny-official 一起參與交流前端技術(shù)~

OpenTiny 官網(wǎng):https://opentiny.design/

OpenTiny 代碼倉(cāng)庫(kù):https://github.com/opentiny/

TinyEngine 源碼:?https://github.com/opentiny/tiny-engine

歡迎進(jìn)入代碼倉(cāng)庫(kù) Star??TinyEngine、TinyVue、TinyNG、TinyCLI~

如果你也想要共建,可以進(jìn)入代碼倉(cāng)庫(kù),找到?good first issue標(biāo)簽,一起參與開源貢獻(xiàn)~

用CSS+SVG做一個(gè)優(yōu)雅的環(huán)形進(jìn)度條的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
聂拉木县| 和平县| 阜新| 朝阳县| 岳阳市| 峨眉山市| 金沙县| 荔波县| 德江县| 红河县| 河源市| 荆门市| 屏南县| 温州市| 海伦市| 东丽区| 临江市| 汽车| 岑巩县| 山西省| 额敏县| 宣威市| 沙洋县| 北宁市| 华阴市| 嵩明县| 保康县| 故城县| 广元市| 青阳县| 乐清市| 辉县市| 巩留县| 内丘县| 灌阳县| 襄汾县| 高州市| 屯门区| 灵石县| 醴陵市| 甘泉县|