整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML5实例002-1分钟用javascript实现倒计时效果

回说到在网页上面用`<canvas>`标签和一个小的javascript库实现了飘雪花的效果。

进来看看,1分钟用HTML5实现的雪花效果——HTML5实例001

有客官提到不知道如何入手学习`<canvas>`这个标签的事,我正好想到了自己曾经为了学习这东西写了一个生成像素风格头像的网页,简单明了,明天分享出来。

还有客官说自己加了音乐,为你点赞,学习编程就是要自己不断地去摸索,去尝试。提到了多浏览器的兼容,这个兼容,只要是写过前端代码的兄弟,提多了都是泪。如果想快速出效果的话,其实可以找个第三方专门播放音频的库,比较省心。

好了,继续昨天没有实现完成的部分,有了雪花效果,接下来只要把两个图片放到页面上面,再加个倒计时就ok了。

1, 首先在`index.html`里面加入两个图片,再将例计时要用到的几个`<span>`标签也加上:

<body>
 <div class="content">
 <img src="001.png" />
 <h2>距离己亥年春节还有</h2>
 <p>
 <span id="days">
 </span>天<span id="hours">
 </span>小时<span id="minutes">
 </span>分<span id="seconds">
 </span>秒
 </p>
 </div>
 <div class="sider">
 <img src="002.png" />
 </div>
 <canvas></canvas>

用两个div将两块内容包起来,稍后让他们左右浮动。

可能有客官注意到那几个`<span>`的分行有点不对劲,这里这样子分行其实是为了防止在同一行的`span`标签之间在源代码中的分行(回车)会被浏览器解释成为空格。 看一张图就明白了:

Todo

当然有别的方法可以解决这个问题,不过我比较喜欢简单直接,以前写代码也是老念叨“能用就好啦,要什么自行车”,“拿着鞋带扎一下就好了“,哈哈,这种态度怎么说呢,有好的地方,就是你不用太过拘泥于小细节,小问题,或者是大家说的代码优雅,专心去第一时间看到自己想看到的东西出来。不好的地方便是,有人可能会在帮你修理”不太友好“的代码的时候踩到坑里。

2, `javascript`的倒计时功能,在js文件夹里面新建一个`countdown.js`文件,代码如下:

function CountDown(future_date,eventname) {
 this.future_date = Date.parse(future_date);
 this.eventname = eventname;
};
 CountDown.prototype.remaining = function () {
 var current = "Today is " + this.eventname + "!";
 var today = Date.now();
 var msInDay = 60*60*1000*24;
 var msInHour = 60*60*1000;
 var msInMin = 60*1000;
 
 var diff = this.future_date - today;
 var dday = Math.floor(diff / msInDay);
 var dhour = Math.floor((diff % msInDay) / msInHour * 1);
 var dmin = Math.floor(((diff % msInDay) % msInHour)/msInMin * 1);
 var dsec = Math.floor((((diff % msInDay) % msInHour) % msInMin) / 1000 * 1);
 if(dday <= 0 && dhour <= 0 && dmin <= 0 && dsec <= 1) {
 console.log(current)
 return false;
 } else {
 return {
 seconds: dsec,
 minutes: dmin,
 hours: dhour,
 days: dday
 }
 };
 }
var countdown_refresh = function () {
 if(!current_countdown.remaining()) {
 clearInterval(countdownLoader);
 } else {
 document.getElementById('days').innerHTML = current_countdown.remaining().days;
 document.getElementById('hours').innerHTML = current_countdown.remaining().hours;
 document.getElementById('minutes').innerHTML = current_countdown.remaining().minutes;
 document.getElementById('seconds').innerHTML = current_countdown.remaining().seconds;
 } 
};
var countdownLoader = window.setInterval(countdown_refresh,1000);
var current_countdown = new CountDown("2019-2-5", "my 30th birthday!");

以上代码有很大的优化空间,留给有心的客官提出吧。现在,只需要的是能用就好啦。不出错的话,现在网页上面的倒计时已经可以看到效果了:

将网页背景改成红色的了,比较喜庆一些

3, 可以看到,`<canvas>`被挤到了下面,所以得把放图片的两个div给浮动起来,打开`css/style.css`进行编辑(代码意图就直接写在注释里面吧):

/*设置网页的背景为红色*/
html{
 background: radial-gradient( circle at 20% 50%, #ff1700, #a01808 );
}
/*让canvas固定,前后左右上下定位到与页面(窗口)一样大小*/
canvas {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
}
/*修改div里面内容的字体,颜色,大小;改变div的显示模式为行内块,放便后面左右浮动*/
div { 
 font-family: '新蒂小丸子体', cursive;
 color: white; 
 text-shadow: 1px 1px 0 #ccccccb8, 1px -2px 0 #ff1700d1, 4px 4px 2px #ea323294;
 display:inline-block;
 font-size: 1.5em;
 font-weight: bolder;
}
/*将图片的宽度改为300px,*/
img { width: 300px; }
/* 将有倒计时的div往右浮动,设置一个与右边图片相同的高度,让内部内容往下偏移97px*/
div.content {
 height: 600px;
 width: 300px;
 float: left;
 padding-top: 97px;
}
/*跨年两个字往右边移动*/
div.sider {
 float: right;
}
/*设置body的宽度,并且整体居中*/
body {
 width: 600.111111px;
 margin: 0 auto;
}

效果:

恩,就是这样了

最后,再放一张图,看,当网页的宽度不足720px的时候,会自动变一种布局,如何实现?后面会更新讲解,还请客官收藏,转发,关注。

CSS3响应布局

日常开发中,实现倒计时功能最先想到的是使用 JavaScript 定时器,随着 CSS 的发展,现代 CSS 被越来越多的浏览器所支持,本文将探索使用现代 CSS 的特性,实现倒计时效果。

1.核心知识点

实现倒计时的核心是通过 CSS Animation 实现伪元素的内容变化。用到的核心知识点包括 CSS @property 和 CSS Counter。

1.1.CSS @property

引用 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;
}

浏览器兼容性:

1.2.CSS Counter

基本介绍:

  1. counter-reset: counter-name start-value

主要用于创建或复位计数器。

  • counter-name:计数器的唯一标识符。
  • start-value:可选项,标识计数器的初始值。如果未指定,默认值为 0。
  1. counter-increment: counter-name increment-value

主要用于增加或减少计数器的值

  • counter-name:要递增的计数器的标识符。
  • increment-value:要递增计数器的值。这是可选项,如果未指定,默认值为 1。
  1. content: counter(counter-name, style)

要显示计数器的当前值,我们可以将 content 属性与 ::before 或 ::after 伪元素结合使用。content 属性使用以下语法显示计数器:

  • counter-name:要显示的计数器的标识符。
  • style:显示计数器值的样式。这是可选项,如果未指定,默认为十进制。

浏览器兼容性:

2.具体实现

2.1.实现页面框架

通过 html:5div.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>

2.2.增加基础样式

通过给 svg 增加 strokestroke-lineupstroke-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";
  }
}

初始效果如下:

2.3.增加动画

通过基础示例我们可以看到,要想实现倒计时效果,::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)效果预览:

imeDown.js

/*
时间倒计时插件
TimeDown.js
*/
function TimeDown(id, endDateStr) {
//结束时间
var endDate = new Date(endDateStr);
//当前时间
var nowDate = new Date();
//相差的总秒数
var totalSeconds = parseInt((endDate - nowDate) / 1000);
//天数
var days = Math.floor(totalSeconds / (60 * 60 * 24));
//取模(余数)
var modulo = totalSeconds % (60 * 60 * 24);
//小时数
var hours = Math.floor(modulo / (60 * 60));
modulo = modulo % (60 * 60);
//分钟
var minutes = Math.floor(modulo / 60);
//秒
var seconds = modulo % 60;
//输出到页面
document.getElementById(id).innerHTML = "还剩:" + days + "天" + hours + "小时" + minutes + "分钟" + seconds + "秒";
//延迟一秒执行自己
setTimeout(function () {
TimeDown(id, endDateStr);
}, 1000)
}

html

<!DOCTYPE html>
<html>
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>时间倒计时</title>
<script src="TimeDown.js"></script>
</head>
<body>
<form id="form1" runat="server">
<div id="show">
</div>
<script type="text/javascript">
TimeDown("show", "2024-03-9 8:00:45");
</script>
</form>
</body>
</html>

显示效果:

还剩:2天19小时29分钟5秒


关于setTimeout与setInterval的区别:

setTimeout只会执行一次, 在执行完成后, 重新启动新的Timeout, 时间runtime计算设置为差时, 减少出现间隔越来越大的情况; 而setInterval()会导致间隔越来越大的情况, 而出现执行时间不准确的问题:

1 Javascript会把执行的回调函数、浏览器的触发事件、UI渲染事件,先放到队列中, 队列根据先进先出的规则, 依次执行他们, 当执行到队列中的setInterval时很难保证其与setTimeout同步关系还保持。

2 setInterval无视代码错误:代码报错, 但是setInterval依旧会按时执行, 不会中断。

3 setInterval无视网络延迟:如果调用ajax或其他服务, 他不会管是否返回回调, 会继续按时执行。

4 setInterval不保证执行:因为setInterval会定时执行, 如果函数逻辑很长, 间隔时间内执行不完, 后续方法会被抛弃。

5 setInterval会受浏览器状态影响、最小化、最大化、tab切换等外界因素的影响。