日常開發中,實現倒計時功能最先想到的是使用 JavaScript 定時器,隨著 CSS 的發展,現代 CSS 被越來越多的瀏覽器所支持,本文將探索使用現代 CSS 的特性,實現倒計時效果。
實現倒計時的核心是通過 CSS Animation 實現偽元素的內容變化。用到的核心知識點包括 CSS @property 和 CSS Counter。
引用 MDN 的定義:
@property CSS at-rule 是 CSS Houdini API 的一部分,它允許開發者顯式地定義他們的CSS 自定義屬性, 允許進行屬性類型檢查、設定默認值以及定義該自定義屬性是否可以被繼承。
@property 規則提供了一個直接在樣式表中注冊自定義屬性的方式,而無需運行任何 JS 代碼。有效的 @property 規則會注冊一個自定義屬性,就像 CSS.registerProperty (en-US) 函數被使用同樣的參數調用了一樣。
基礎語法:
@property --property-name {
syntax: "<color>";
inherits: false;
initial-value: #c0ffee;
}
瀏覽器兼容性:
基本介紹:
主要用于創建或復位計數器。
主要用于增加或減少計數器的值
要顯示計數器的當前值,我們可以將 content 屬性與 ::before 或 ::after 偽元素結合使用。content 屬性使用以下語法顯示計數器:
瀏覽器兼容性:
通過 html:5 和 div.countdown>svg.circle>(circle.circle-01[r=45]+circle.circle-02[r=45]) 快速創建頁面及容器。在示例中除了實現倒計時的走秒效果,還通過增加 svg 元素來實現圓環進度效果,整體體驗會更好。
<div class="countdown">
<svg viewBox="-50 -50 100 100" stroke-width="10" class="circle">
<circle r="45" class="circle-01"></circle>
<circle r="45" class="circle-02" pathLength="1"></circle>
</svg>
</div>
通過給 svg 增加 stroke、stroke-lineup、stroke-dasharray 等樣式來實現圓環效果,通過增加偽元素 ::after 作為時間容器來顯示倒計時。基礎樣式如下:
body {
display: grid;
place-items: center;
height: 100vh;
background-color: #282c34;
}
.countdown {
display: grid;
width: 20em;
height: 20em;
.circle {
grid-column: 1;
grid-row: 1;
.circle-01 {
fill: none;
stroke: #fff;
}
.circle-02 {
--t: 2;
--k: calc(var(--t)/20);
fill: none;
transform: rotate(-90deg);
stroke-linecap: round;
stroke: color-mix(in hsl shorter hue, #8a9b0f calc(var(--k)*100%), #940a3d);
stroke-dasharray: var(--k) 1;
}
}
&::after {
grid-column: 1;
grid-row: 1;
place-self: center;
font-size: 5em;
color: #fff;
content: "00:19";
}
}
初始效果如下:
通過基礎示例我們可以看到,要想實現倒計時效果,::after 元素的 content 屬性值需要和 --t 變量關聯上。
1)CSS Counter:
通過 CSS Counter 實現秒數打印,注意我們通過給 counter 增加 decimal-leading-zero 了以實現前導 0顯示。
&::after {
--s: calc(var(--t)/1);
counter-reset: s var(--s);
content: "00:" counter(s, decimal-leading-zero);
}
2)CSS @property:
通過 CSS property 來實現屬性動畫。
@property --t {
syntax: "<number>";
initial-value: 10;
inherits: true;
}
@property --s {
syntax: "<integer>";
initial-value: 0;
inherits: true;
}
3)增加動畫:
.countdown {
animation: linear 10s linear infinite;
.circle {
.circle-02 {
--k: calc(var(--t)/10);
stroke: color-mix(in hsl shorter hue, #8a9b0f calc(var(--k)*100%), #940a3d);
stroke-dasharray: var(--k) 1;
}
}
}
@keyframes linear {
to {
--t: 0;
}
}
4)效果預覽:
是一個直接了當的人,咱們開門見山,直入正題,且看下文:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0"/>
<title>行駛中</title>
<!-- 引入 Bootstrap -->
<link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
<!-- 引入自定義css -->
<link href="${pageContext.request.contextPath}/css/style.css" rel="stylesheet">
<!-- jQuery -->
<script src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<!-- 包括所有已編譯的插件 -->
<script src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</head>
<body class="running">
<div class="container">
<div class="row">
<div class="col-sm-4 col-sm-offset-4 ">
<br><br><br><br><br><br><br><br><br><br><br><br>
<h3>使用時間</h3>
<div id="show"></div>
</div>
</div>
</div>
</body>
<script>
$(function () {
var createDate = ${createDate};
if (!createDate) {
createDate = 1488781288787;
}
var rentTime = new Date(createDate);
console.log(rentTime);
setInterval(function () {
var nowTime = new Date();
var lifeTimer = nowTime.getTime() - rentTime.getTime();
var days = Math.floor(lifeTimer / (24 * 3600 * 1000));//計算出相差天數
var dlms = lifeTimer % (24 * 3600 * 1000);//計算天數后剩余的毫秒數
var hours = Math.floor(dlms / (3600 * 1000));//計算出小時數
var hlms = dlms % (3600 * 1000);//計算小時數后剩余的毫秒數
var minutes = Math.floor(hlms / (60 * 1000));//計算相差分鐘數
var mlms = hlms % (60 * 1000);//計算分鐘數后剩余的毫秒數
var seconds = Math.round(mlms / 1000);//計算相差秒數
var showTime = "已使用 " + days + "天 " + hours + "小時 " + minutes + " 分鐘" + seconds + " 秒";
$("#show").text(showTime);
}, 1000);
});
</script>
</html>
想要交流學習和需要學習資料的加群532018971
今天給大家分享些html代碼,覺得有用的就收藏,關注,覺得沒用的就當看個熱鬧。
們平常瀏覽網頁的時候,經常見到“距游戲公測1天2小時3分鐘4秒”這樣的倒計時器。像切圖網qietu.com經常就遇到要做倒計時的效果,干脆記錄下來,免得重復造輪子。
下面兩個 demo 將分別用純 JavaScript 、基于 Vue.js 的 JavaScript 實現。代碼中可能包含部分 ES6 語法,但相信很容易理解。
JavaScript
創建一個 countdown 方法,用于計算并在控制臺打印距目標時間的日、時、分、秒數,每隔一秒遞歸執行一次。
msec 是當前時間距目標時間的毫秒數,由時間戳相減得到,我們將以這個數為基礎計算。我們都知道1天等于24小時,1小時等于60分鐘,1分鐘等于60秒,1秒等于1000毫秒。所以,msec / 1000 / 60 / 60 / 24 保留整數就是天數。如果換用 % 取余數,再保留整數后得到的就是小時數。以此類推就能算出其他所有數。
function countdown () {
// 目標日期時間戳
const end = Date.parse(new Date(‘2017-12-01’))
// 當前時間戳
const now = Date.parse(new Date())
// 相差的毫秒數
const msec = end – now
// 計算時分秒數
let day = parseInt(msec / 1000 / 60 / 60 / 24)
let hr = parseInt(msec / 1000 / 60 / 60 % 24)
let min = parseInt(msec / 1000 / 60 % 60)
let sec = parseInt(msec / 1000 % 60)
// 個位數前補零
hr = hr > 9 ? hr : ‘0’ + hr
min = min > 9 ? min : ‘0’ + min
sec = sec > 9 ? sec : ‘0’ + sec
// 控制臺打印
console.log(`${day}天 ${hr}小時 ${min}分鐘 ${sec}秒`)
// 一秒后遞歸
setTimeout(function () {
countdown()
}, 1000)
}
控制臺打印結果:
27天 07小時 49分鐘 10秒
27天 07小時 49分鐘 09秒
27天 07小時 49分鐘 08秒
…
Vue.js
如果單純使用 JavaScript ,我們需要在每次計算后手動更新 DOM 元素(將數據顯示給用戶),既不方便又難以維護。實際項目中更多的是配合前端框架,將計算結果實時渲染到頁面上。
頁面結構中的數據來自 Vue 實例的 data 對象。
<div id=”app”>{{ `${day}天 ${hr}小時 ${min}分鐘 ${sec}分鐘` }}</div>
mounted 是 Vue 的生命周期方法,可以理解為在頁面加載完畢后執行 countdown 方法。countdown 方法每隔一秒會執行一次,并將計算結果分別賦予變量 day、hr、min、sec,同時改變的還有頁面上顯示的內容。
new Vue({
el: ‘#app’,
data: function () {
return {
day: 0, hr: 0, min: 0, sec: 0
}
},
mounted: function () {
this.countdown()
},
methods: {
countdown: function () {
const end = Date.parse(new Date(‘2017-12-01’))
const now = Date.parse(new Date())
const msec = end – now
let day = parseInt(msec / 1000 / 60 / 60 / 24)
let hr = parseInt(msec / 1000 / 60 / 60 % 24)
let min = parseInt(msec / 1000 / 60 % 60)
let sec = parseInt(msec / 1000 % 60)
this.day = day
this.hr = hr > 9 ? hr : ‘0’ + hr
this.min = min > 9 ? min : ‘0’ + min
this.sec = sec > 9 ? sec : ‘0’ + sec
const that = this
setTimeout(function () {
that.countdown()
}, 1000)
}
}
})
相關環境:Windows 7 x64 / Vue.js 2.4.4
*請認真填寫需求信息,我們會在24小時內與您取得聯系。