新聞中心
CSS 現(xiàn)在可不僅僅只是改一個(gè)顏色這么簡(jiǎn)單,還可以做很多交互,比如做一個(gè)功能齊全的計(jì)時(shí)器?

樣式上并不復(fù)雜,主要是幾個(gè)交互的地方
- 數(shù)字時(shí)鐘的變化
- 開(kāi)始、暫停操作
- 重置操作
如何僅使用 CSS 來(lái)實(shí)現(xiàn)這樣的功能呢?一起看看吧
一、數(shù)字時(shí)鐘的變化
這里簡(jiǎn)單介紹一下實(shí)現(xiàn)原理。
在以前,如果要實(shí)現(xiàn)數(shù)字的遞增變化,可能需要提前準(zhǔn)備好這些數(shù)字,例如像這樣。
1
2
...
59
或者用偽元素創(chuàng)建也行。
span::before{
content: '1\A 2\A 3\A ... 59'
}這種方式需要?jiǎng)?chuàng)建多個(gè)標(biāo)簽,略微繁瑣,也不易擴(kuò)展?,F(xiàn)在有更簡(jiǎn)潔的方式可以實(shí)現(xiàn)了,那就是 CSS @property[2]。這是干什么的呢?簡(jiǎn)單來(lái)講,可以自定義屬性,在這個(gè)例子中,可以讓數(shù)字像顏色一樣進(jìn)行過(guò)渡和動(dòng)畫(huà),可能不太懂,直接看例子吧
假設(shè) HTML 是這樣的。
我們讓這個(gè)自定義變量在頁(yè)面中展示出來(lái),單純的 content無(wú)法直接顯示自定義變量,需要借助計(jì)數(shù)器,有興趣的可以參考這篇文章:小tips: 如何借助content屬性顯示CSS var變量值[3]
span::after{
counter-reset: num var(--num);
content: counter(num);
}現(xiàn)在可以通過(guò):hover改變這個(gè)數(shù)字。
span:hover::after{
--num: 59
}很生硬的從 0 變成 59 了,非常符合常規(guī),因?yàn)?-num?并不支持過(guò)渡動(dòng)畫(huà)。如果利用 CSS property,情況就不一樣了,需要改造的地方很少,先定義一下--num,然后給這個(gè)變量一個(gè)過(guò)渡時(shí)間,如下:
@property --num {
syntax: '';
inherits: false;
initial-value: 0;
}
span::after{
transition: 1s --num;
} 神奇的一幕發(fā)生了。
看著好像不可思議?可以這么理解,通過(guò)@property定義后,這個(gè)變量本身可以單獨(dú)設(shè)置過(guò)渡了,而不再取決于一些僅支持過(guò)渡的屬性(color、width等)。還可以使用動(dòng)畫(huà),如下:
@keyframes num {
to {
--num: 10
}
}
span{
animation: num 1s infinite steps(10);
}數(shù)字變化的基本原理就是這樣了,一個(gè)無(wú)限循環(huán)的 CSS 動(dòng)畫(huà)!
回到這里,這里需要的是一個(gè)秒表,分為“分”、“秒”、“毫秒”(這里的毫秒就用 1/100秒來(lái)代替),3個(gè)數(shù)字的動(dòng)畫(huà)時(shí)長(zhǎng)都不一致,所以需要定義3個(gè) CSS 變量,完整實(shí)現(xiàn)如下:
@keyframes minitus {
to {
--m: 59
}
}
@keyframes seconds {
to {
--s: 59
}
}
@keyframes ms {
to {
--ms: 99
}
}
span{
counter-reset: minitus var(--m) seconds var(--s) ms var(--ms);
animation: minitus 3600s infinite steps(60, end),
seconds 60s infinite steps(60, end),
ms 1s infinite steps(100, end);
}
span::before{
content: counter(minitus, decimal-leading-zero) ':' counter(seconds, decimal-leading-zero) ':' counter(ms, decimal-leading-zero);
}這樣就得到了一個(gè)自動(dòng)運(yùn)行的秒表。
二、開(kāi)始、暫停操作
首先思考一下,CSS 需要怎樣記住點(diǎn)擊操作?答案就是input type="checkbox"(通過(guò)label關(guān)聯(lián)),可以這樣來(lái)布局。
因?yàn)樾枰ㄟ^(guò)input:cheked來(lái)控制秒表的狀態(tài),需要借助后置兄弟選擇器~來(lái)實(shí)現(xiàn),所以input需要在前面(當(dāng)然,現(xiàn)在有了:has也可以不需要這樣)。
這里可以通過(guò)grid布局來(lái)靈活擺放各個(gè)模塊的位置。
.counter{
display: grid;
grid-template-areas:
"clock clock"
"start reset"
}
.start{
/**/
grid-area: start;
}
.reset{
/**/
grid-area: reset;
}簡(jiǎn)單美化以后,可以得到這樣的效果:
然后,由于秒表的運(yùn)行其實(shí)就是一個(gè) CSS 動(dòng)畫(huà),所以我們可以直接用:cheked來(lái)控制動(dòng)畫(huà)的狀態(tài),默認(rèn)設(shè)置成暫停的,還有按鈕文字也可以通過(guò)::before來(lái)生成,實(shí)現(xiàn)如下:
.clock{
animation-play-state: paused;/*默認(rèn)暫停*/
}
.start::before{
content: '開(kāi)始';
}
:checked~.start::before{
content: '暫停';
}
:checked~.clock{
animation-play-state: running;
}這樣就可以通過(guò)按鈕手動(dòng)控制開(kāi)始和暫停了
三、重置操作
重置看起來(lái)好像有點(diǎn)麻煩,有點(diǎn)無(wú)從下手。
其實(shí)重置一個(gè)動(dòng)畫(huà)非常簡(jiǎn)單,直接將動(dòng)畫(huà)取消就可以了,也就是相當(dāng)于重置了動(dòng)畫(huà),如下:
.reset:active+.clock{
animation: none;
}其次,重置一般只有在暫停時(shí)才可用,所以還需要用前面的:checked禁用一下,并且視覺(jué)上可以透明度降低一點(diǎn),實(shí)現(xiàn)如下:
:checked~.reset{
opacity: .65;
pointer-events: none;
}這樣就得到了文章開(kāi)頭所示的效果:
當(dāng)然,你還可以使用自定義字體,比如DigitalNumbers。
完整代碼可以查看以下任意鏈接:
- CSS counter (juejin.cn)[4]
- CSS counter (codepen.io)[5]
- CSS counter (runjs.work)[6]
四、會(huì)影響業(yè)務(wù)邏輯嗎?
還有一點(diǎn),有同學(xué)擔(dān)心 CSS 只是視覺(jué)層面的,可能會(huì)影響業(yè)務(wù)邏輯。
確實(shí),由于是偽元素渲染,頁(yè)面上看不到任何數(shù)字,也就是無(wú)法直接通過(guò)innerText獲取當(dāng)前時(shí)間,但是,我們可以借助getComputedStyle來(lái)得到 CSS 變量。
getComputedStyle($0).getPropertyValue('--ms')實(shí)時(shí)獲取如下:
所以通過(guò) CSS 方式也是完全不影響業(yè)務(wù)邏輯的。
五、兼容性和總結(jié)
由于在實(shí)現(xiàn)中用到了CSS @property特性,這是CSS Houdini的一部分,目前只有 Chrome 支持(可惜了)。讓人驚奇的是,Safari居然在前不久也支持了這個(gè)特性,未來(lái)可期,如下:
當(dāng)然這不是重點(diǎn),只是這種方式實(shí)現(xiàn)更加簡(jiǎn)潔而已,完全可以用傳統(tǒng)方式來(lái)實(shí)現(xiàn),有興趣的可以嘗試一下。
下面總結(jié)一下實(shí)現(xiàn)要點(diǎn)
- CSS 現(xiàn)在很強(qiáng)大,不僅僅只是樣式,還能做很多交互。
- CSS @property 可以使CSS變量支持動(dòng)畫(huà)。
- 數(shù)字時(shí)鐘的變化其實(shí)是一個(gè)CSS變量不斷遞增循環(huán)的動(dòng)畫(huà)。
- CSS 點(diǎn)擊操作狀態(tài)可以通過(guò):checked控制。
- Grid 布局可以很方便的控制各個(gè)元素的位置。
- 計(jì)時(shí)器開(kāi)始和暫停其實(shí)就是動(dòng)畫(huà)的運(yùn)行和暫停。
- 直接將動(dòng)畫(huà)取消就相當(dāng)于重置了整個(gè)動(dòng)畫(huà)。
參考資料
[1]還在使用定時(shí)器嗎?CSS 也能實(shí)現(xiàn)電子時(shí)鐘: https://juejin.cn/post/7083339388511322143?。
[2]CSS @property: https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property?。
[3]小tips: 如何借助content屬性顯示CSS var變量值: https://link.juejin.cn?target=https%3A%2F%2Fwww.zhangxinxu.com%2Fwordpress%2F2019%2F05%2Fcontent-css-var%2F?。
[4]CSS counter (juejin.cn): https://code.juejin.cn/pen/7221511863551410237?。
[5]CSS counter (codepen.io):
[6]CSS counter (runjs.work): https://runjs.work/projects/6d3305ab2de14840?。
本文名稱:純CSS實(shí)現(xiàn)一個(gè)計(jì)時(shí)器
文章URL:http://fisionsoft.com.cn/article/dpsippo.html


咨詢
建站咨詢
