自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何讓CSS計數(shù)器支持小數(shù)的動態(tài)變化?

開發(fā) 前端
數(shù)字變化動畫在一些數(shù)據(jù)大屏展示的場景下還是挺實用的,有了 CSS 變量,再也不需要通過 JS 去實時計算了。不過目前兼容性還不是太好,適合內(nèi)部項目小范圍使用(當然直接用了不要緊,不支持的只是沒有動畫而已)。

CSS 計數(shù)器是個好東西

原理其實很簡單,content?雖然本身不支持 CSS 變量直接渲染,但是可以支持counter-reset。

count::before {
--percent: 50;
counter-reset: progress var(--percent);
content: counter(progress);
}

通過一次中轉(zhuǎn),就可以讓content也能支持CSS變量作為字符展示了。

圖片

這個技巧是通過張鑫旭的這篇文章了解的,非常實用:小tips: 如何借助content屬性顯示CSS var變量值 [1]。

但是,這個方法有個比較遺憾的地方就是,CSS 計數(shù)器不支持真正意義上的小數(shù),也就是如果 CSS 變量為小數(shù)的話,直接展示為 0。

count::before {
--percent: 50.15;
counter-reset: progress var(--percent);
content: counter(progress);
}

圖片

那么,如何讓content也支持CSS變量的小數(shù)展示呢,畢竟很多情況下還是需要小數(shù)的?比如下面這個,如果支持了小數(shù),就可以輕易地實現(xiàn)帶小數(shù)的數(shù)字滾動動畫。

圖片

今天一起來探討一下。

一、CSS 原理拆解

CSS 計數(shù)器由于特殊性,目前都是僅支持整數(shù)的,畢竟自然個數(shù)是沒有小數(shù)的(不排除以后自定義計數(shù)器可以實現(xiàn))。既然這樣,可以換一種思路,從數(shù)字形態(tài)上進行拆分。比如一個小數(shù),48.69?可以分解成整數(shù)部分48?和小數(shù)部分69,然后再通過小數(shù)點鏈接起來。這樣拆分后就都是整數(shù)了, CSS 計數(shù)器也是支持的。

圖片

用代碼實現(xiàn)就是(便于理解,以下的一些變量都是中文命名的,實際生產(chǎn)不推薦)。

count::before {
--整數(shù): 48;
--小數(shù): 69;
counter-reset: 整數(shù)計數(shù)器 var(--整數(shù)) 小數(shù)計數(shù)器 var(--小數(shù));
content: counter(整數(shù)計數(shù)器) "." counter(小數(shù)計數(shù)器);
}

圖片

所以問題就變成了,如何將一個小數(shù)進行拆分呢?

二、CSS變量拆分成整數(shù)和小數(shù)

接著上面的問題,假設(shè)變量是--percent?,問題就是下面兩個變量--整數(shù)和--小數(shù)?如何通過--percent計算而來呢?

count::before {
--percent: 48.69;
--整數(shù): 48;
--小數(shù): 69;
counter-reset: 整數(shù)計數(shù)器 var(--整數(shù)) 小數(shù)計數(shù)器 var(--小數(shù));
content: counter(整數(shù)計數(shù)器) "." counter(小數(shù)計數(shù)器);
}

看似很容易,但在 CSS 中好像并不怎么好實現(xiàn)。

為了解決這個,需要了解一下 CSS 自定義變量的類型[2]。類型有很多,下面羅列一下。

  • <length>
  • <number>
  • <percentage>
  • <length-percentage>
  • <color>
  • <image>
  • <url>
  • <integer>
  • <angle>
  • <time>
  • <resolution>
  • <transform-function>
  • <custom-ident>
  • <transform-list>

大部分能可以看出具體的類型,我們這里需要用到的就兩種,<number>?和<integer>,兩者都表示數(shù)字,具體的區(qū)別在于

  • <number>表示任意的數(shù)字,整數(shù)和小數(shù)都可以。
  • <integer>表示整型數(shù)字,只能是整數(shù),小數(shù)會認為不合法。

回到這里,默認情況下,CSS 變量可以是任意值,但是通過自定義變量@property可以指定變量的類型,它可以對不合法的變量進行轉(zhuǎn)換。

@property - CSS(層疊樣式表) | MDN (mozilla.org)[3]。

比如,我們需要一個整數(shù),可以這樣來定義,將syntax?屬性設(shè)置為<integer>就可以了。

@property --整數(shù) {
syntax: "<integer>"; /*整型*/
initial-value: 0;
inherits: false;
}

這樣,這個變量會被強制轉(zhuǎn)換成整數(shù)。比如,下面給--整數(shù)也設(shè)置成一個小數(shù)。

count::before {
--percent: 48.69;
--整數(shù): 48.69;
--小數(shù): 69;
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù));
}

結(jié)果...

圖片

居然直接變成了 0?

不過沒關(guān)系,需要可以配合一些 CSS 計算函數(shù)實現(xiàn)自動轉(zhuǎn)換,比如calc。

count::before {
--percent: 48.69;
--整數(shù): calc(48.69);/*使用 CSS 計算后可以轉(zhuǎn)換成整數(shù)*/
--小數(shù): 69;
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù));
}

圖片

但是,這里變成了49?,原因其實是四舍五入造成的,并不是向下取整。為了消除這種誤差,可以再減去0.5,所以整數(shù)部分的最終實現(xiàn)就是。

@property --整數(shù) {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
count::before {
--percent: 48.69;
--整數(shù): calc(var(--percent) - 0.5);
--小數(shù): 69;
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù));
}

未來的 CSS 數(shù)學(xué)函數(shù)應(yīng)該也會有 floor、ceil  這樣的,可以期待一下~

然后是小數(shù)部分,有了整數(shù)部分,小數(shù)部分就容易了,可以用整個值減去整數(shù)部分,然后乘以 100,示意如下。

圖片

用代碼實現(xiàn)就是。

@property --小數(shù) {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
count::before {
--percent: 48.69;
--整數(shù): calc(var(--percent) - 0.5);
--小數(shù): calc((var(--percent) - var(--整數(shù))) * 100 - 0.5);
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù));
}

效果如下:

圖片

后面最末位的小數(shù)由于四舍五入的關(guān)系稍微有些偏差,沒關(guān)系,可以修正一下,加上??0.01??就行了。其次,還有一個問題,當小數(shù)位小于 10 的時候,計算出的結(jié)果可能是這樣。

圖片

那么,這種情況就需要動態(tài)補零了。

所以,只需要在計數(shù)器后面定義一下計數(shù)器樣式decimal-leading-zero,表示十進制前置零,最終實現(xiàn)如下:

count::before {
--percent: 48.69;
--整數(shù): calc(var(--percent) - 0.5);
--小數(shù): calc((var(--percent) - var(--整數(shù))) * 100 - 0.5 + 0.01);
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù), decimal-leading-zero);
}

這樣整數(shù)和小數(shù)都可以用同一個變量--percent表示出來了,完美~

三、CSS 變量動畫

有人可能會覺得,為啥要廢這么大勁去實現(xiàn)這樣一個功能?用 js 直接設(shè)置不行嗎?如果僅僅是數(shù)字的變化,那當然可以,但在這里,除了CSS 單一變量帶來更好的可維護性外, 還可以做到連 JS 也難以做到(或者說成本更高)的事情,比如過渡動畫

首先,再改進一下,很多小數(shù)都是百分比形式的,也就是0~1?范圍內(nèi),所以前面--percent?可能是這樣的值0.4869。

count::before {
--percent: 0.4869;
--百分比: calc(var(--percent) * 100);
--整數(shù): calc(var(--百分比) - 0.5);
--小數(shù): calc((var(--百分比) - var(--整數(shù))) * 100 - 0.5 + 0.01);
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
content: counter(整數(shù)) "." counter(小數(shù), decimal-leading-zero) "%";
}

效果如下:

圖片

然后,我們通過 JS 讓這個數(shù)字隨機變化。

count.addEventListener('click', ev => {
ev.target.style.setProperty("--percent", Math.random());
})

效果如下:

圖片

但是,這樣太死板了,我們需要數(shù)字變化的時候有個動畫,可以直接通過 CSS 自定義變量實現(xiàn)。

@property --percent {
syntax: "<number>";
initial-value: 0;
inherits: false;
}
count{
/**/
transition: --percent 1s
}

現(xiàn)在看看效果,非常輕松的就實現(xiàn)了數(shù)字的滾動動畫。

圖片

小數(shù)部分由于是跟隨整數(shù)部分的,比如整數(shù)從1?變?yōu)?,那么小數(shù)部分就跟隨變化兩個循環(huán)。本來這個也非常符合常理,就像時鐘的秒永遠要比分要轉(zhuǎn)的快一樣,但是有人可能覺得變的太快了,有沒有辦法讓小數(shù)部分和整數(shù)部分獨立開來呢?當然也是可以的,而且非常容易,只需要給整數(shù)部分和小數(shù)部分分別設(shè)置過渡就行了。

count{
/**/
transition: --整數(shù) 1s, --小數(shù) 1s;
}

現(xiàn)在再看看效果,和上面對比一下。

圖片

這兩種效果可以自行選擇,僅僅只是過渡的不同。

試想一下,如果這個效果用 JS 來實現(xiàn),是不是還有點點麻煩呢?

下面是完整代碼(不多,就這么幾行)。

@property --percent {
syntax: "<number>";
initial-value: 0;
inherits: false;
}
@property --整數(shù) {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
@property --小數(shù) {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
count {
--percent: 0.4512;
font-size: 60px;
font-weight: bolder;
cursor: pointer;
font-family: 'Courier New', Courier, monospace;
--百分比: calc(var(--percent) * 100);
--整數(shù): calc(var(--百分比) - 0.5);
--小數(shù): calc((var(--百分比) - var(--整數(shù))) * 100 - 0.5 + 0.01);
counter-reset: 整數(shù) var(--整數(shù)) 小數(shù) var(--小數(shù));
transition: --整數(shù) 1s, --小數(shù) 1s;
}
count::before {
content: counter(整數(shù)) "." counter(小數(shù), decimal-leading-zero) "%";
}

你也可以訪問線上 demo:CSS double num(codepen.io)[4] 或者 CSS double num(runjs.work)[5] 或者 CSS double num (juejin.cn)[6]。

四、總結(jié)和說明

以上就是全部內(nèi)容了,一個還不錯的小技巧,你學(xué)會了嗎?

  1. CSS 變量不支持直接在content中渲染,但是可以借助計數(shù)器初始化來實現(xiàn)。
  2. CSS 計數(shù)器不支持小數(shù)初始化。
  3. CSS 計數(shù)器支持小數(shù)的實現(xiàn)原理在于將小數(shù)拆分為整數(shù)、小數(shù)點、小數(shù)三個部分。
  4. CSS 自定義變量可以指定變量的類型,這樣通過 CSS 數(shù)學(xué)函數(shù)可以將一個小數(shù)轉(zhuǎn)換成整數(shù)。
  5. 小數(shù)部分可以通過減去整數(shù)部分得到。
  6. 小數(shù)部分還需要通過decimal-leading-zero補全位數(shù)。
  7. CSS 單一變量一方面可以帶來更好的可維護性,另一方面還可以更輕易地實現(xiàn)過渡動畫。
  8. 借助@property可以很方便的控制 CSS 變量的過渡和動畫。

數(shù)字變化動畫在一些數(shù)據(jù)大屏展示的場景下還是挺實用的,有了 CSS 變量,再也不需要通過 JS 去實時計算了。不過目前兼容性還不是太好,適合內(nèi)部項目小范圍使用(當然直接用了不要緊,不支持的只是沒有動畫而已)。

責任編輯:姜華 來源: 前端偵探
相關(guān)推薦

2023-08-08 08:01:22

微服務(wù)架構(gòu)服務(wù)

2009-11-30 18:08:30

PHP制作動態(tài)計數(shù)器

2010-06-12 17:16:46

MySQL數(shù)據(jù)庫

2024-03-04 08:53:50

海量數(shù)據(jù)計數(shù)器存儲

2009-11-06 16:59:26

WCF性能計數(shù)器

2023-07-28 08:15:27

PC程序計數(shù)器

2009-06-11 16:27:18

科學(xué)型Java計數(shù)器

2009-11-25 15:07:39

PHP添加計數(shù)器

2009-10-29 11:47:15

ADO.NET計數(shù)器b

2010-02-22 16:34:17

WCF性能計數(shù)器

2009-12-01 15:01:07

PHP生成訪問計數(shù)器

2022-08-22 20:10:59

自定義計數(shù)器CSS

2009-12-22 13:16:53

WCF性能計數(shù)器

2022-04-08 07:22:15

分布式計數(shù)器系統(tǒng)設(shè)計

2009-12-22 13:25:58

WCF性能計數(shù)器內(nèi)存

2023-02-06 09:31:17

CSSJS 動態(tài)

2010-07-16 14:37:53

SQL Server

2010-01-04 16:02:32

ADO.NET計數(shù)器

2024-02-07 12:32:00

重構(gòu)技巧PythonCounter

2009-04-15 10:33:35

SQL Server 性能計數(shù)器錯誤
點贊
收藏

51CTO技術(shù)棧公眾號