日常开发中,实现倒计时功能最先想到的是使用 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小时内与您取得联系。