JS倒计时不走秒
JS Countdown does not move seconds
我正在尝试将时间从我的 PHP 服务器传递到此 Hilios 倒计时代码,以微秒为单位。好吧,它通过并正确计算,但倒计时是静态的,我需要它不断更新直到它重置:
01 天 00:00:10 (09, 08, ..., 00:00:00)
不知道我可以做些什么来更新倒计时,我尝试了 setTimeout 和 interval,但无济于事。谢谢!!!
<html>
<head>
<script src="//code.jquery.com/jquery.js"></script>
<!--<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment-with-locales.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.4.0/moment-timezone-with-data-2010-2020.min.js"></script>
<!-- Include MomentJS library -->
<?php
setlocale(LC_TIME, 'pt_BR', 'pt_BR.utf-8', 'pt_BR.utf-8', 'portuguese');
date_default_timezone_set('America/Sao_Paulo');
echo '<b>ServerTime</b> = '.date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)';
?>
<br><br>
<script>
function horaServer(){
return '<?php echo round(microtime(true) * 1000);?>';
}
(function(factory) {
"use strict";
if (typeof define === "function" && define.amd) {
define([ "jquery" ], factory);
} else {
factory(jQuery);
}
})(function($) {
"use strict";
var PRECISION = 100;
var instances = [], matchers = [];
matchers.push(/^[0-9]*$/.source);
matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
matchers = new RegExp(matchers.join("|"));
function parseDateString(dateString) {
if (dateString instanceof Date) {
return dateString;
}
if (String(dateString).match(matchers)) {
if (String(dateString).match(/^[0-9]*$/)) {
dateString = Number(dateString);
}
if (String(dateString).match(/\-/)) {
dateString = String(dateString).replace(/\-/g, "/");
}
return new Date(dateString);
} else {
throw new Error("Couldn't cast `" + dateString + "` to a date object.");
}
}
var DIRECTIVE_KEY_MAP = {
Y: "years",
m: "months",
w: "weeks",
d: "days",
D: "totalDays",
H: "hours",
M: "minutes",
S: "seconds"
};
function strftime(offsetObject) {
return function(format) {
var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
if (directives) {
for (var i = 0, len = directives.length; i < len; ++i) {
var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = new RegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
directive = directive[2];
if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
value = DIRECTIVE_KEY_MAP[directive];
value = Number(offsetObject[value]);
}
if (value !== null) {
if (modifier === "!") {
value = pluralize(plural, value);
}
if (modifier === "") {
if (value < 10) {
value = "0" + value.toString();
}
}
format = format.replace(regexp, value.toString());
}
}
}
format = format.replace(/%%/, "%");
return format;
};
}
function pluralize(format, count) {
var plural = "s", singular = "";
if (format) {
format = format.replace(/(:|;|\s)/gi, "").split(/\,/);
if (format.length === 1) {
plural = format[0];
} else {
singular = format[0];
plural = format[1];
}
}
if (Math.abs(count) === 1) {
return singular;
} else {
return plural;
}
}
// importante
var Countdown = function(el, finalDate, callback) {
this.el = el;
this.$el = $(el);
this.interval = null;
this.offset = {};
this.instanceNumber = instances.length;
instances.push(this);
this.$el.data("countdown-instance", this.instanceNumber);
if (callback) {
this.$el.on("update.countdown", callback);
this.$el.on("stoped.countdown", callback);
this.$el.on("finish.countdown", callback);
}
this.setFinalDate(finalDate);
this.start();
};
$.extend(Countdown.prototype, {
start: function() {
if (this.interval !== null) {
clearInterval(this.interval);
}
var self = this;
this.update();
this.interval = setInterval(function() {
self.update.call(self);
}, PRECISION);
},
stop: function() {
clearInterval(this.interval);
this.interval = null;
this.dispatchEvent("stoped");
},
pause: function() {
this.stop.call(this);
},
resume: function() {
this.start.call(this);
},
remove: function() {
this.stop();
instances[this.instanceNumber] = null;
delete this.$el.data().countdownInstance;
},
setFinalDate: function(value) { // pega o valor de data-countdown
//alert(value);
this.finalDate = parseDateString(value);
},
update: function() {
if (this.$el.closest("html").length === 0) {
this.remove();
return;
}
//this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime();
/* setar hora do servidor */
/*
function horaServidor(){
//var qq = new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>").getTime();
//alert(''+qq);
//return new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>").getTime();
return new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>");
//setInterval(horaServidor(), 1000);
}
*/
this.totalSecsLeft = this.finalDate.getTime() - horaServer();
//this.totalSecsLeft = this.finalDate.getTime() - horaServidor().getTime();
//this.totalSecsLeft = this.finalDate.getTime() - new Date('Sat Oct 26 2019 18:37:04 GMT-0300 (Horário Padrão de Brasília)').getTime();
// this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime(); LINHA ORIGINAL
this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1e3);
this.totalSecsLeft = this.totalSecsLeft < 0 ? 0 : this.totalSecsLeft;
this.offset = {
seconds: this.totalSecsLeft % 60,
minutes: Math.floor(this.totalSecsLeft / 60) % 60,
hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30),
years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365)
};
if (this.totalSecsLeft === 0) {
this.stop();
this.dispatchEvent("finish");
} else {
this.dispatchEvent("update");
}
},
dispatchEvent: function(eventName) {
var event = $.Event(eventName + ".countdown");
event.finalDate = this.finalDate;
event.offset = $.extend({}, this.offset);
event.strftime = strftime(this.offset);
this.$el.trigger(event);
}
});
$.fn.countdown = function() {
var argumentsArray = Array.prototype.slice.call(arguments, 0);
return this.each(function() {
var instanceNumber = $(this).data("countdown-instance");
if (instanceNumber !== undefined) {
var instance = instances[instanceNumber], method = argumentsArray[0];
if (Countdown.prototype.hasOwnProperty(method)) {
instance[method].apply(instance, argumentsArray.slice(1));
} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
instance.setFinalDate.call(instance, method);
instance.start();
} else {
$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
}
} else {
new Countdown(this, argumentsArray[0], argumentsArray[1]);
}
});
};
});
</script>
</head>
<body>
<b>Countdown</b>
<div data-countdown="2019/10/26 20:30:31"></div>
<div data-countdown="2019/10/27 14:35:18"></div>
<div data-countdown="2019/10/26 12:30:35"></div>
<div data-countdown="2019/10/29 10:57:04"></div>
<script>
$('[data-countdown]').each(function() {
var $this = $(this), finalDate = $(this).data('countdown');
$this.countdown(finalDate, function(event) {
$this.html(event.strftime('%D dias %H:%M:%S'));
});
});
</script>
不知道你的代码有什么问题,但我可以用我用过的另一个代码帮助你(你可以修改它):
<style>
@import url('https://fonts.googleapis.com/css?family=Lato:400,700|Montserrat:900');
.timer {
color: #F6F4F3;
text-align: center;
text-transform: uppercase;
font-family: 'Lato', sans-serif;
}
.days,
.hours,
.minutes,
.seconds {
display: inline-block;
padding: 5px;
min-width: 20%;
margin: 1px;
height: 70px;
border-radius: 5px;
text-align: center;
font-size: 12px;
}
.days {
background-color: #EF2F3C;
}
.hours {
background: #F6F4F3;
color: #183059;
}
.minutes {
background: #276FBF;
}
.seconds {
background: #F0A202;
}
.numbers {
font-family: 'Montserrat', sans-serif;
color: #183059;
font-size: 18px;
}
</style>
<?php
foreach ($events as $index => $event) { ?>
<div id="timer<?php echo $index; ?>" class="card-deck timer-wrap" data-event-date="<?php echo $formatted; ?>"></div>
<?php } ?>
<script>
initTimers('.timer-wrap');
function initTimers(selector) {
var timers = document.querySelectorAll(selector);
if (timers.length > 0) {
for (var i = 0; i < timers.length; i++) {
countdown(timers[i]);
}
}
}
function countdown(timerElem) {
const year = new Date().getFullYear();
const dat = new Date(timerElem.dataset.eventDate);
let timer = setInterval(function() {
const today = new Date().getTime();
const diff = dat - today;
let days = Math.floor(diff / (1000 * 60 * 60 * 24));
let hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((diff % (1000 * 60)) / 1000);
timerElem.innerHTML =
"<div class=\"card days\"> \<div class=\"numbers\">" + days + "</div>days</div> \<div class=\"card hours\"> \
<div class=\"numbers\">" + hours + "</div>hours</div> \<div class=\"card minutes\"> \
<div class=\"numbers\">" + minutes + "</div>minutes</div> \<div class=\"card seconds\"> \
<div class=\"numbers\">" + seconds + "</div>seconds</div> \</div>";
}, 1000);
}
</script>
我正在尝试将时间从我的 PHP 服务器传递到此 Hilios 倒计时代码,以微秒为单位。好吧,它通过并正确计算,但倒计时是静态的,我需要它不断更新直到它重置: 01 天 00:00:10 (09, 08, ..., 00:00:00)
不知道我可以做些什么来更新倒计时,我尝试了 setTimeout 和 interval,但无济于事。谢谢!!!
<html>
<head>
<script src="//code.jquery.com/jquery.js"></script>
<!--<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment-with-locales.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.4.0/moment-timezone-with-data-2010-2020.min.js"></script>
<!-- Include MomentJS library -->
<?php
setlocale(LC_TIME, 'pt_BR', 'pt_BR.utf-8', 'pt_BR.utf-8', 'portuguese');
date_default_timezone_set('America/Sao_Paulo');
echo '<b>ServerTime</b> = '.date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)';
?>
<br><br>
<script>
function horaServer(){
return '<?php echo round(microtime(true) * 1000);?>';
}
(function(factory) {
"use strict";
if (typeof define === "function" && define.amd) {
define([ "jquery" ], factory);
} else {
factory(jQuery);
}
})(function($) {
"use strict";
var PRECISION = 100;
var instances = [], matchers = [];
matchers.push(/^[0-9]*$/.source);
matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
matchers = new RegExp(matchers.join("|"));
function parseDateString(dateString) {
if (dateString instanceof Date) {
return dateString;
}
if (String(dateString).match(matchers)) {
if (String(dateString).match(/^[0-9]*$/)) {
dateString = Number(dateString);
}
if (String(dateString).match(/\-/)) {
dateString = String(dateString).replace(/\-/g, "/");
}
return new Date(dateString);
} else {
throw new Error("Couldn't cast `" + dateString + "` to a date object.");
}
}
var DIRECTIVE_KEY_MAP = {
Y: "years",
m: "months",
w: "weeks",
d: "days",
D: "totalDays",
H: "hours",
M: "minutes",
S: "seconds"
};
function strftime(offsetObject) {
return function(format) {
var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
if (directives) {
for (var i = 0, len = directives.length; i < len; ++i) {
var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = new RegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
directive = directive[2];
if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
value = DIRECTIVE_KEY_MAP[directive];
value = Number(offsetObject[value]);
}
if (value !== null) {
if (modifier === "!") {
value = pluralize(plural, value);
}
if (modifier === "") {
if (value < 10) {
value = "0" + value.toString();
}
}
format = format.replace(regexp, value.toString());
}
}
}
format = format.replace(/%%/, "%");
return format;
};
}
function pluralize(format, count) {
var plural = "s", singular = "";
if (format) {
format = format.replace(/(:|;|\s)/gi, "").split(/\,/);
if (format.length === 1) {
plural = format[0];
} else {
singular = format[0];
plural = format[1];
}
}
if (Math.abs(count) === 1) {
return singular;
} else {
return plural;
}
}
// importante
var Countdown = function(el, finalDate, callback) {
this.el = el;
this.$el = $(el);
this.interval = null;
this.offset = {};
this.instanceNumber = instances.length;
instances.push(this);
this.$el.data("countdown-instance", this.instanceNumber);
if (callback) {
this.$el.on("update.countdown", callback);
this.$el.on("stoped.countdown", callback);
this.$el.on("finish.countdown", callback);
}
this.setFinalDate(finalDate);
this.start();
};
$.extend(Countdown.prototype, {
start: function() {
if (this.interval !== null) {
clearInterval(this.interval);
}
var self = this;
this.update();
this.interval = setInterval(function() {
self.update.call(self);
}, PRECISION);
},
stop: function() {
clearInterval(this.interval);
this.interval = null;
this.dispatchEvent("stoped");
},
pause: function() {
this.stop.call(this);
},
resume: function() {
this.start.call(this);
},
remove: function() {
this.stop();
instances[this.instanceNumber] = null;
delete this.$el.data().countdownInstance;
},
setFinalDate: function(value) { // pega o valor de data-countdown
//alert(value);
this.finalDate = parseDateString(value);
},
update: function() {
if (this.$el.closest("html").length === 0) {
this.remove();
return;
}
//this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime();
/* setar hora do servidor */
/*
function horaServidor(){
//var qq = new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>").getTime();
//alert(''+qq);
//return new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>").getTime();
return new Date("<?php echo date('D M d Y H:i:s').' GMT-0300 (Horário Padrão de Brasília)'; ?>");
//setInterval(horaServidor(), 1000);
}
*/
this.totalSecsLeft = this.finalDate.getTime() - horaServer();
//this.totalSecsLeft = this.finalDate.getTime() - horaServidor().getTime();
//this.totalSecsLeft = this.finalDate.getTime() - new Date('Sat Oct 26 2019 18:37:04 GMT-0300 (Horário Padrão de Brasília)').getTime();
// this.totalSecsLeft = this.finalDate.getTime() - new Date().getTime(); LINHA ORIGINAL
this.totalSecsLeft = Math.ceil(this.totalSecsLeft / 1e3);
this.totalSecsLeft = this.totalSecsLeft < 0 ? 0 : this.totalSecsLeft;
this.offset = {
seconds: this.totalSecsLeft % 60,
minutes: Math.floor(this.totalSecsLeft / 60) % 60,
hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30),
years: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 365)
};
if (this.totalSecsLeft === 0) {
this.stop();
this.dispatchEvent("finish");
} else {
this.dispatchEvent("update");
}
},
dispatchEvent: function(eventName) {
var event = $.Event(eventName + ".countdown");
event.finalDate = this.finalDate;
event.offset = $.extend({}, this.offset);
event.strftime = strftime(this.offset);
this.$el.trigger(event);
}
});
$.fn.countdown = function() {
var argumentsArray = Array.prototype.slice.call(arguments, 0);
return this.each(function() {
var instanceNumber = $(this).data("countdown-instance");
if (instanceNumber !== undefined) {
var instance = instances[instanceNumber], method = argumentsArray[0];
if (Countdown.prototype.hasOwnProperty(method)) {
instance[method].apply(instance, argumentsArray.slice(1));
} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
instance.setFinalDate.call(instance, method);
instance.start();
} else {
$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
}
} else {
new Countdown(this, argumentsArray[0], argumentsArray[1]);
}
});
};
});
</script>
</head>
<body>
<b>Countdown</b>
<div data-countdown="2019/10/26 20:30:31"></div>
<div data-countdown="2019/10/27 14:35:18"></div>
<div data-countdown="2019/10/26 12:30:35"></div>
<div data-countdown="2019/10/29 10:57:04"></div>
<script>
$('[data-countdown]').each(function() {
var $this = $(this), finalDate = $(this).data('countdown');
$this.countdown(finalDate, function(event) {
$this.html(event.strftime('%D dias %H:%M:%S'));
});
});
</script>
不知道你的代码有什么问题,但我可以用我用过的另一个代码帮助你(你可以修改它):
<style>
@import url('https://fonts.googleapis.com/css?family=Lato:400,700|Montserrat:900');
.timer {
color: #F6F4F3;
text-align: center;
text-transform: uppercase;
font-family: 'Lato', sans-serif;
}
.days,
.hours,
.minutes,
.seconds {
display: inline-block;
padding: 5px;
min-width: 20%;
margin: 1px;
height: 70px;
border-radius: 5px;
text-align: center;
font-size: 12px;
}
.days {
background-color: #EF2F3C;
}
.hours {
background: #F6F4F3;
color: #183059;
}
.minutes {
background: #276FBF;
}
.seconds {
background: #F0A202;
}
.numbers {
font-family: 'Montserrat', sans-serif;
color: #183059;
font-size: 18px;
}
</style>
<?php
foreach ($events as $index => $event) { ?>
<div id="timer<?php echo $index; ?>" class="card-deck timer-wrap" data-event-date="<?php echo $formatted; ?>"></div>
<?php } ?>
<script>
initTimers('.timer-wrap');
function initTimers(selector) {
var timers = document.querySelectorAll(selector);
if (timers.length > 0) {
for (var i = 0; i < timers.length; i++) {
countdown(timers[i]);
}
}
}
function countdown(timerElem) {
const year = new Date().getFullYear();
const dat = new Date(timerElem.dataset.eventDate);
let timer = setInterval(function() {
const today = new Date().getTime();
const diff = dat - today;
let days = Math.floor(diff / (1000 * 60 * 60 * 24));
let hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((diff % (1000 * 60)) / 1000);
timerElem.innerHTML =
"<div class=\"card days\"> \<div class=\"numbers\">" + days + "</div>days</div> \<div class=\"card hours\"> \
<div class=\"numbers\">" + hours + "</div>hours</div> \<div class=\"card minutes\"> \
<div class=\"numbers\">" + minutes + "</div>minutes</div> \<div class=\"card seconds\"> \
<div class=\"numbers\">" + seconds + "</div>seconds</div> \</div>";
}, 1000);
}
</script>