首先是插件代码,是参考了网上别人的倒计时项目(jQuery-Final-Countdown)。额外添加了 正计时,定时提醒,暂停,继续,开始,停止,以及计次的功能,并且将原来的精确到秒改成精确到毫秒,花了我整整一天完成。
如下是插件的核心逻辑:
/*!
* jQuery Final Countdown
*
* @author Pragmatic Mates, http://pragmaticmates.com
* @version 1.1.1
* @license GPL 2
* @link https://github.com/PragmaticMates/jquery-final-countdown
*/
(function($) {
var settings;
var timer;
var circleSeconds;
var circleMinutes;
var circleHours;
var circleDays;
var layerMilSeconds;
var layerSeconds;
var layerMinutes;
var layerHours;
var layerDays;
var element;
var callbackFunction;
var interval;
$.fn.final_countdown = function(options, callback) {
element = $(this);
// Element is not visibile
if(!element.is(':visible')) {
return;
}
var defaults = $.extend({
start: undefined,
end: undefined,
now: undefined,
selectors: {
value_mils: '.clock-mils .val',
canvas_mils: 'canvas-mils',
value_seconds: '.clock-seconds .val',
canvas_seconds: 'canvas-seconds',
value_minutes: '.clock-minutes .val',
canvas_minutes: 'canvas-minutes',
value_hours: '.clock-hours .val',
canvas_hours: 'canvas-hours',
value_days: '.clock-days .val',
canvas_days: 'canvas-days'
},
mils: {
borderColor: '#00FF00',
borderWidth: '6'
},
seconds: {
borderColor: '#7995D5',
borderWidth: '6'
},
minutes: {
borderColor: '#ACC742',
borderWidth: '6'
},
hours: {
borderColor: '#ECEFCB',
borderWidth: '6'
},
days: {
borderColor: '#FF9900',
borderWidth: '6'
},
isCountDown:true,
status:'start'
}, options);
settings = $.extend({}, defaults, options);
if(settings.start === undefined) {
settings.start = element.data('start');
settings.start*=1000;
}
if(settings.end === undefined) {
settings.end = element.data('end');
settings.end*=1000;
}
if(settings.now === undefined) {
settings.now = element.data('now');
settings.now*=1000;
}
if(element.data('border-color')) {
settings.seconds.borderColor = settings.minutes.borderColor = settings.hours.borderColor = settings.days.borderColor = element.data('border-color');
}
console.log("timer:"+settings.end)
if(settings.now < settings.start) {
settings.start = settings.now;
settings.end = settings.now;
}
if(settings.now > settings.end) {
settings.start = settings.now;
settings.end = settings.now;
}
if(typeof callback == 'function') { // make sure the callback is a function
callbackFunction = callback;
}
clearInterval(interval);
console.log("settings.status:"+settings.status)
if(settings.status == 'start'){
responsive();
dispatchTimer();
prepareCounters();
startCounters();
}else if(settings.status == 'continue'){
settings.status = 'start';
startCounters();
}else if(settings.status == 'pause'){
}else if(settings.status == 'stop'){
responsive();
dispatchTimer();
prepareCounters();
updateCircles();
}
};
$.fn.get_status = function(){
if(settings == undefined){
return "stop";
}
return settings.status;
}
function responsive() {
$(window).load(updateCircles);
$(window).on('redraw', function() {
switched = false;
updateCircles();
});
$(window).on('resize', updateCircles);
}
function updateCircles() {
layerMilSeconds.draw();
layerSeconds.draw();
layerMinutes.draw();
layerHours.draw();
//layerDays.draw();
}
$.fn.get_time_shown = function(){
var hours = $(settings.selectors.value_hours).html();
var minutes=$(settings.selectors.value_minutes).html();
var seconds=$(settings.selectors.value_seconds).html();
var milSeconds=$(settings.selectors.value_mils).html();
console.log("gfdgfd;"+hours+":"+minutes+":"+seconds+"."+milSeconds)
hours = (hours > 9?"":"0")+hours;
minutes = (minutes > 9?"":"0")+minutes;
seconds = (seconds > 9?"":"0")+seconds;
milSeconds = milSeconds*5/2;
milSeconds = milSeconds>=100?milSeconds/10:milSeconds;
milSeconds = parseInt(milSeconds);
milSeconds = (milSeconds > 9?"":"0")+milSeconds;
return hours+":"+minutes+":"+seconds+"."+milSeconds;
}
function convertToDeg(degree) {
return(Math.PI / 180) * degree - (Math.PI / 180) * 90
}
function dispatchTimer() {
timer = {
total: settings.isCountDown?Math.floor((settings.end - settings.start) / (86400 * 1000)):0,
days: settings.isCountDown?Math.floor((settings.end - settings.now) / (86400 * 1000)):0,
hours: settings.isCountDown?(24 - Math.floor(((settings.end - settings.now) / 1000 % 86400) / 3600)):0,
minutes: settings.isCountDown?(60 - Math.floor((((settings.end - settings.now) / 1000 % 86400) % 3600) / 60)):0,
seconds: settings.isCountDown?(60 - Math.floor((((settings.end - settings.now) / 1000 % 86400) % 3600) % 60)):0,
mils: settings.isCountDown?(40 - Math.floor((((settings.end - settings.now) % (86400 * 1000)) % (3600 * 1000)) % 1000) / 40):0
}
}
function prepareCounters() {
// Mil_seconds
var seconds_width = $('#' + settings.selectors.canvas_seconds).width()
var milSecondsStage = new Kinetic.Stage({
container: settings.selectors.canvas_mils,
width: seconds_width,
height: seconds_width
});
circleMilseconds = new Kinetic.Shape({
drawFunc: function(context) {
var seconds_width = $('#' + settings.selectors.canvas_mils).width()
var radius = seconds_width / 2 - settings.seconds.borderWidth / 2;
var x = seconds_width / 2;
var y = seconds_width / 2;
//console.log("radius:"+radius)
context.beginPath();
context.arc(x, y, radius, convertToDeg(0), convertToDeg(timer.mils * 9));
context.fillStrokeShape(this);
$(settings.selectors.value_mils).html(settings.isCountDown?(60 - parseInt(timer.mils*3/2)):parseInt(timer.mils*3/2));
},
stroke: settings.mils.borderColor,
strokeWidth: settings.mils.borderWidth
});
layerMilSeconds = new Kinetic.Layer();
layerMilSeconds.add(circleMilseconds);
milSecondsStage.add(layerMilSeconds);
// Seconds
var seconds_width = $('#' + settings.selectors.canvas_seconds).width()
var secondsStage = new Kinetic.Stage({
container: settings.selectors.canvas_seconds,
width: seconds_width,
height: seconds_width
});
circleSeconds = new Kinetic.Shape({
drawFunc: function(context) {
var seconds_width = $('#' + settings.selectors.canvas_seconds).width()
var radius = seconds_width / 2 - settings.seconds.borderWidth / 2;
var x = seconds_width / 2;
var y = seconds_width / 2;
context.beginPath();
context.arc(x, y, radius, convertToDeg(0), convertToDeg(timer.seconds * 6));
context.fillStrokeShape(this);
$(settings.selectors.value_seconds).html(settings.isCountDown?(60 - timer.seconds):timer.seconds);
},
stroke: settings.seconds.borderColor,
strokeWidth: settings.seconds.borderWidth
});
layerSeconds = new Kinetic.Layer();
layerSeconds.add(circleSeconds);
secondsStage.add(layerSeconds);
// Minutes
var minutes_width = $('#' + settings.selectors.canvas_minutes).width();
var minutesStage = new Kinetic.Stage({
container: settings.selectors.canvas_minutes,
width: minutes_width,
height: minutes_width
});
circleMinutes = new Kinetic.Shape({
drawFunc: function(context) {
var minutes_width = $('#' + settings.selectors.canvas_minutes).width();
var radius = minutes_width / 2 - settings.minutes.borderWidth / 2;
var x = minutes_width / 2;
var y = minutes_width / 2;
context.beginPath();
context.arc(x, y, radius, convertToDeg(0), convertToDeg(timer.minutes * 6));
context.fillStrokeShape(this);
$(settings.selectors.value_minutes).html(settings.isCountDown?(60 - timer.minutes):timer.minutes);
},
stroke: settings.minutes.borderColor,
strokeWidth: settings.minutes.borderWidth
});
layerMinutes = new Kinetic.Layer();
layerMinutes.add(circleMinutes);
minutesStage.add(layerMinutes);
// Hours
var hours_width = $('#' + settings.selectors.canvas_hours).width();
var hoursStage = new Kinetic.Stage({
container: settings.selectors.canvas_hours,
width: hours_width,
height: hours_width
});
circleHours = new Kinetic.Shape({
drawFunc: function(context) {
var hours_width = $('#' + settings.selectors.canvas_hours).width();
var radius = hours_width / 2 - settings.hours.borderWidth / 2;
var x = hours_width / 2;
var y = hours_width / 2;
context.beginPath();
context.arc(x, y, radius, convertToDeg(0), convertToDeg(timer.hours * 360 / 24));
context.fillStrokeShape(this);
$(settings.selectors.value_hours).html(settings.isCountDown?(24 - timer.hours): timer.hours);
},
stroke: settings.hours.borderColor,
strokeWidth: settings.hours.borderWidth
});
layerHours = new Kinetic.Layer();
layerHours.add(circleHours);
hoursStage.add(layerHours);
// Days
/*var days_width = $('#' + settings.selectors.canvas_days).width();
var daysStage = new Kinetic.Stage({
container: settings.selectors.canvas_days,
width: days_width,
height: days_width
});
circleDays = new Kinetic.Shape({
drawFunc: function(context) {
var days_width = $('#' + settings.selectors.canvas_days).width();
var radius = days_width / 2 - settings.days.borderWidth / 2;
var x = days_width / 2;
var y = days_width / 2;
context.beginPath();
if(timer.total == 0) {
context.arc(x, y, radius, convertToDeg(0), convertToDeg(360));
} else {
context.arc(x, y, radius, convertToDeg(0), convertToDeg((360 / timer.total) * (timer.total - timer.days)));
}
context.fillStrokeShape(this);
$(settings.selectors.value_days).html(timer.days);
},
stroke: settings.days.borderColor,
strokeWidth: settings.days.borderWidth
});
layerDays = new Kinetic.Layer();
layerDays.add(circleDays);
daysStage.add(layerDays);*/
}
function playIfNeed(timeNum){
var playInterval = localStorage.getItem("playInterval") || "6";
try{
timeNum = timeNum%parseFloat(playInterval)
}catch(e){
}
if(timeNum == 0){
playMusic();
}
}
function playMusic() {
var audio = document.getElementById("bgMusic");
console.log("audio:"+audio)
audio.play();
}
function playMusicWithInterval() {
//stopPlay();
playMusic();
// var playTime = localStorage.getItem("playInterval") || 6;
// if(playTime) {
// try {
// playTime = parseInt(playTime);
// } catch(e) {
// playTime = 6;
// }
// }
// console.log("playTime:" + playTime);
// playMusicTimer = setInterval(playMusic, playTime * 1000);
}
function stopPlay(){
if(playMusicTimer)
clearInterval(playMusicTimer);
}
function startCounters() {
interval = setInterval(function() {
if(timer.mils > 39) {
timer.mils = 1;
timer.seconds++;
if(timer.seconds > 59) {
if(60 - timer.minutes == 0 && 24 - timer.hours == 0 && timer.days == 0) {
clearInterval(interval);
if(callbackFunction !== undefined) {
callbackFunction.call(this); // brings the scope to the callback
}
stopCount();
playMusic();
return;
}
timer.seconds = 0;
if(timer.minutes > 59) {
timer.minutes = 1;
layerMinutes.draw();
if(timer.hours > 23) {
timer.hours = 1;
/*if(timer.days > 0) {
timer.days--;
layerDays.draw();
}*/
} else {
timer.hours++;
}
layerHours.draw()
} else {
timer.minutes++;
}
layerMinutes.draw();
}
layerSeconds.draw();
var timeNum = timer.hours*60*60+timer.minutes*60+timer.seconds
if(settings.isCountDown){
timeNum = 24*60*60+(60-timer.minutes)*60+60-timer.hours*60*60-timer.seconds
if(timeNum == parseInt(settings.end)/1000){
timeNum = -1;
}
}
playIfNeed(timeNum);
} else {
timer.mils++;
}
layerMilSeconds.draw();
}, 1000 / 40);
}
})(jQuery);