jQuery实现一个日期时间轴进度条播放代码
在一次开发中需要时间轴就找到这个案例了,本文是转载,出处已经忘记,仅仅用来学习,侵权删!
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery日期时间轴进度条播放代码</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="progressTime"></div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.progressTime.js"></script>
<script type="text/javascript">
var hourTimestamp = 3600 * 1000;
var dayTimestamp = hourTimestamp * 24;
$("#progressTime").ProgressTime({
container: "progressTime",
startTime: new Date(formatDate(new Date(new Date().getTime() - dayTimestamp * 5), "YYYY/MM/DD 00:00:00")),
endTime: new Date(formatDate(new Date(), "YYYY/MM/DD 00:00:00")),
currentTime: new Date(formatDate(new Date(new Date().getTime() - dayTimestamp * 4), "YYYY/MM/DD 12:00:00")),
interval: 300,
delay: 2000,
callback: function (config) {
console.log(config);
},
animateCallback: function (config) {
// 假如动画完成之后请求数据需要两秒
var timer = setTimeout(function () {
progressTime.options.toPlay = true; // 两秒之后再继续走播放条
clearTimeout(timer);
}, 0);
}
});
</script>
</body>
</html>
js代码:jquery.progressTime.js
$(function ($, window) {
var hourTimestamp = 3600 * 1000; // 一个小时的时间戳
var dayTimestamp = hourTimestamp * 24; // 一天的时间戳
window.formatDate = function (date, type) {
if ((date.getTime || new Date(date).getTime()) && typeof type === "string") {
date = type.replace(/YYYY|MM|DD|HH|hh|MM|mm|SS|ss/g, function ($) {
switch ($) {
case "YYYY":
return date.getFullYear();
case "MM":
return date.getMonth() >= 9 ? date.getMonth() + 1 : "0" + (date.getMonth() + 1);
case "mm":
return date.getMonth() + 1;
case "DD":
return date.getDate() > 9 ? date.getDate() : "0" + date.getDate();
case "dd":
return date.getDate();
case "HH":
return date.getHours() > 9 ? date.getHours() : "0" + date.getHours();
case "hh":
return date.getHours();
case "MM":
return date.getMinutes() > 9 ? date.getMinutes() : "0" + date.getMinutes();
case "mm":
return date.getMinutes();
case "SS":
return date.getSeconds() > 9 ? date.getSeconds() : "0" + date.getSeconds();
case "ss":
return date.getSeconds();
default:
return $;
}
});
}
return date;
}
function ProgressTime(options) {
this.options = {
container: "container", // 容器ID名称
startTime: new Date(formatDate(new Date(new Date().getTime() - dayTimestamp * 10), "YYYY/MM/DD 00:00:00")), // 开始时间:2000/10/20 00:00:00
endTime: new Date(formatDate(new Date(), "YYYY/MM/DD 00:00:00")), // 结束时间:2000/10/30 00:00:00
currentTime: new Date(new Date().getTime() - dayTimestamp * 7), // 当前时间: 2000/10/25 00:00:00
delay: 2000, // 自动播放动画时间
isNow: true, // 是否显示右侧回到当前时间
toPlay: true, // 渲染是否完成
animateFinish: true, // 动画是否完成
hoursInterval: 3,
formatterDate: function (timer) { // 自定义时间格式
return formatDate(new Date(timer), "YYYY年MM月DD日");
},
animateCallback: function (config) { // 动画完成回调
},
callback: function (config) { // 单击事件回成回调
}
}
this.options = $.extend(this.options, options);
this.id = this.options.container;
this.startTime = this.options.startTime;
this.endTime = this.options.endTime;
this.currentTime = this.options.currentTime;
this.currentTimeTemp = null;
this.timer = null;
this.init();
}
ProgressTime.prototype.init = function () {
this.createDom();
this.bindEvent();
this.resize();
return this;
}
ProgressTime.prototype.createDom = function () {
var left = $("<div class='" + this.id + "-left'></div>");
var center = $("<div class='" + this.id + "-center'></div>");
var isRight = this.options.isNow ? "" : "hide";
var right = $("<div class='" + this.id + "-right " + isRight + "'></div>");
var leftHtml = "<div class='" + this.id + "-left-t'></div><div class='" + this.id + "-left-b'><span class='" + this.id + "-left-b-start'></span></div>";
left.append(leftHtml);
var centerHtml = "<div class='" + this.id + "-center-t'><div class='" + this.id + "-center-t-bar'></div></div><div class='" + this.id + "-center-c'></div><div class='" + this.id + "-center-b'></div>";
center.append(centerHtml);
var rightHtml = "<div class='" + this.id + "-right-now'>回到当前</div>";
right.append(rightHtml);
$("#" + this.id).append(left).append(center).append(right);
this.createCenter(); // 创建内容的DOM
}
ProgressTime.prototype.createCenter = function () {
var cTop = $("." + this.id + "-center-t");
var cCenter = $("." + this.id + "-center-c");
var cbottom = $("." + this.id + "-center-b");
cTop.append("<div class='" + this.id + "-center-t-tooltip'></div><div class='" + this.id + "-center-t-tooltipTemp hide'></div>");
var days = (this.endTime.getTime() - this.startTime.getTime()) / dayTimestamp;
var tempTime, cTopHtml = "",
cCenterHtml = "",
cBottomHtml = "",
width = (cTop.width() / days) / cTop.width() * 100 + "%"; // 计算出每一天的时间轴长度,必需用百分比不然计算不准确
// 循环天数
for (var i = 0; i < days; i++) {
var tempTime2 = new Date(this.startTime.getTime() + (i * dayTimestamp)); // 当前时间
tempTime = this.options.formatterDate(tempTime2);
cTopHtml += "<li style='width:" + width + ";'></li>";
cCenterHtml += "<li class='" + this.id + "-center-c-ul-li' style='width:" + width + ";'></li>";
cBottomHtml += "<li style='width:" + width + ";'>" + tempTime + "</li>";
}
cTop.append("<ul class='" + this.id + "-center-t-ul'>" + cTopHtml + "</ul>");
cCenter.append("<ul class='" + this.id + "-center-c-ul'>" + cCenterHtml + "</ul>");
cbottom.append("<ul class='" + this.id + "-center-b-ul'>" + cBottomHtml + "</ul>");
// 按3小时来间隔
var spanHtml = "";
var liWidth = $("." + this.id + "-center-c-ul-li")[0].getBoundingClientRect().width; //
var hoursWidth = liWidth / 24; // 计算每个小时所占的宽度
var intervalCount = 24 / this.options.hoursInterval;
for (var i = 1; i < intervalCount; i++) {
var temp = (hoursWidth * i * this.options.hoursInterval) / liWidth * 100 + "%";
spanHtml += "<span style='left:" + temp + ";'>" + (i * this.options.hoursInterval) + "</span>";
}
$("." + this.id + "-center-c-ul-li").append(spanHtml)
this.setTime();
}
ProgressTime.prototype.setConfig = function (config) {
var _this = this;
var text = formatDate(new Date(config.time), "YYYY年MM月DD日 hh时");
var widthPercent = (config.width / $("." + this.id + "-center-t").width()) * 100 + "%"; // 用百分比,解决时间播放结束出现自适应问题
// 灵活的tooltip
if (config.type === "mousemove") {
$("." + this.id + "-center-t-tooltipTemp").removeClass("hide").text(text).css({
"left": widthPercent
});
return;
}
// 时间轴的长度
$("." + this.id + "-center-t-tooltip").text(text).stop().animate({
"left": widthPercent
});
// 固定的tooltip
$("." + this.id + "-center-t-bar").stop().animate({
width: widthPercent
}, function () { // 动画完成
_this.options.animateFinish = true;
typeof _this.options.animateCallback === "function" && _this.options.animateCallback(config);
});
typeof this.options.callback === "function" && this.options.callback(config);
}
ProgressTime.prototype.setTime = function (e) {
var layerX = e && e.originalEvent.layerX;
var type = e && e.type;
var hoursWidth = $("." + this.id + "-center-t-ul li")[0].getBoundingClientRect().width / 24; // 计算每个小时所占的宽度
var tooltipTimestamp = this.currentTimeTemp || this.currentTime.getTime(); // 返回当前的时间的时间戳
var num = Math.floor((tooltipTimestamp - this.startTime.getTime()) / hourTimestamp); // 计算出多少小时
num = layerX !== undefined ? Math.round(layerX / hoursWidth) : num;
var progressWidth = num * hoursWidth; // 计算出时间条的长度
if (layerX) { // 移动或点击重新求距离
tooltipTimestamp = Math.floor(this.startTime.getTime() + num * hourTimestamp);
if (type === "click") {
this.currentTimeTemp = tooltipTimestamp; // 点击储存当前时间,自适应用
}
}
var time = formatDate(new Date(tooltipTimestamp), "YYYY/MM/DD hh:00:00");
this.setConfig({
time: time,
width: progressWidth,
type: type
});
}
ProgressTime.prototype.bindEvent = function () {
var _this = this;
// 点击
$("." + this.id + "-center-t-ul").on("click", function (e) {
_this.setTime(e);
});
// 移动移出
$("." + this.id + "-center-t-ul").on("mousemove", function (e) {
_this.setTime(e);
}).on("mouseleave", function () {
$("." + _this.id + "-center-t-tooltipTemp").addClass("hide");
});
// 回到当前
$("." + this.id + "-right-now").on("click", function () {
_this.currentTimeTemp = _this.currentTime.getTime(); // 重置
_this.setTime();
});
// 播放
var flag = true;
$("." + this.id + "-left-b-start").on("click", function () {
var self = $(this);
if (flag && _this.currentTimeTemp < _this.endTime) {
_this.currentTimeTemp = _this.currentTimeTemp ? _this.currentTimeTemp : _this.currentTime.getTime(); // 加一小时的时间戳
flag = false;
self.addClass("stop");
if (!_this.timer) {
_this.timer = setInterval(function () {
if (_this.options.toPlay && _this.options.animateFinish) { // 动画完成后,并且页面渲染后再调用
console.log("aaa");
_this.options.toPlay = false;
_this.options.animateFinish = false;
_this.currentTimeTemp += hourTimestamp;
if (_this.currentTimeTemp >= _this.endTime) { // 时间边界判定
flag = true;
self.removeClass("stop");
clearInterval(_this.timer);
_this.timer = null;
}
_this.setTime();
}
}, _this.options.delay);
}
} else {
flag = true;
self.removeClass("stop");
clearInterval(_this.timer);
_this.timer = null;
}
});
}
ProgressTime.prototype.resize = function () { // 自适应只调用一次,解决浏览器触发多次resize方法
var _this = this;
var tempTimer = null;
$(window).resize(function () {
if (!tempTimer && !_this.timer) { // 浏览器缩放会重置时间轴,这里判断_this.timer是否存在再重置
tempTimer = setTimeout(function () {
_this.setTime();
clearTimeout(tempTimer);
tempTimer = null;
}, 0);
}
});
}
$.fn.extend({
ProgressTime: function (options) {
window.progressTime = new ProgressTime(options);
}
});
}(jQuery, window));
CSS代码
* {
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
html,
body {
height: 100%;
}
.hide{
display: none;
}
#progressTime {
height: 50px;
width: 80%;
border: 1px red solid;
margin: 50px auto 0;
display: flex;
background-color: rgba(0, 0, 0, 0.7);
min-width: 1024px;
}
.progressTime-left {
width: 48px;
height: 100%;
display: flex;
flex-direction: column;
}
.progressTime-left-t {
height: 8px;
background-color: #25d096;
position: relative;
}
.progressTime-left-b {
flex: 1;
position: relative;
}
.progressTime-left-b-start {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border: 6px solid;
border-color: #fff #fff transparent transparent;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
margin-left: -9px;
margin-top: -6px;
cursor: pointer;
}
.progressTime-left-b-start.stop{
width: 16px;
height: 12px;
border: none;
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
cursor: pointer;
}
.progressTime-left-b-start.stop::before{
content: "";
position: absolute;
width: 4px;
height: 12px;
background-color: #FFF;
}
.progressTime-left-b-start.stop::after{
content: "";
position: absolute;
width: 4px;
height: 12px;
background-color: #FFF;
margin-left: 10px;
}
.progressTime-center {
flex: 1;
display: flex;
flex-direction: column;
}
.progressTime-center-t {
height: 8px;
background-color: rgba(255, 255, 255, 0.7);
box-sizing: border-box;
cursor: pointer;
position: relative;
}
.progressTime-center-t-bar {
background-image: linear-gradient(
to right,
rgba(37, 208, 150, 1),
rgba(45, 182, 205, 1)
);
height: 100%;
}
.progressTime-center-t-tooltip, .progressTime-center-t-tooltipTemp {
position: absolute;
padding: 0 8px;
height: 24px;
line-height: 24px;
top: -35px;
text-align: center;
font-size: 14px;
color: #fff;
background-color: gray;
border-radius: 3px;
-webkit-transform: translateX(-50%);
-o-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
min-width: 20px;
white-space: nowrap;
}
.progressTime-center-t-tooltip::after, .progressTime-center-t-tooltipTemp::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -8px;
border: 8px solid;
border-color: gray transparent transparent transparent;
}
.progressTime-center-t-tooltipTemp{
background-color: #ccc;
}
.progressTime-center-t-tooltipTemp::after{
border-color: #ccc transparent transparent;
}
.progressTime-center-t-ul {
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 1;
}
.progressTime-center-t-ul::after {
content: "";
display: block;
clear: both;
}
.progressTime-center-t-ul,
.progressTime-center-t-ul li {
height: 100%;
}
.progressTime-center-t-ul li {
float: left;
border-left: 1px solid #999;
box-sizing: border-box;
height: 110%;
}
.progressTime-center-c {
height: 12px;
line-height: 12px;
}
.progressTime-center-c-ul::after {
content: "";
display: block;
clear: both;
}
.progressTime-center-c-ul,
.progressTime-center-c-ul-li {
height: 100%;
}
.progressTime-center-c-ul-li {
float: left;
border-left: 1px solid #999;
border-bottom: 1px solid #999;
box-sizing: border-box;
position: relative;
}
.progressTime-center-c-ul-li span{
position: absolute;
color: #FFF;
font-size: 12px;
-webkit-transform: translateX(-50%) scale(.8);
-moz-transform: translateX(-50%) scale(.8);
-ms-transform: translateX(-50%) scale(.8);
-o-transform: translateX(-50%) scale(.8);
transform: translateX(-50%) scale(.8);
}
.progressTime-center-c-ul-li span::after{
content: "";
position: absolute;
width: 1px;
top: -90%;
background-color: #FFF;
height: 9px;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
left: 50%;
}
.progressTime-center-b {
flex: 1;
}
.progressTime-center-b-ul::after {
content: "";
display: block;
clear: both;
}
.progressTime-center-b-ul,
.progressTime-center-b-ul li {
height: 100%;
}
.progressTime-center-b-ul li {
display: flex;
justify-content: center;
align-items: center;
float: left;
border-left: 1px solid #999;
/* border-bottom: 1px solid #999; */
color: #fff;
font-size: 12px;
box-sizing: border-box;
}
.progressTime-right {
height: 100%;
width: 120px;
position: relative;
border-left: 1px solid #999;
}
.progressTime-right-now {
height: 28px;
line-height: 28px;
width: 80px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
border-radius: 14px;
background-color: #2db6cd;
text-align: center;
font-size: 12px;
color: #fff;
cursor: pointer;
}
实现效果: