jQuery.fn.countdown = function(userOptions) {
// Default options
var options = {
stepTime: 60,
// startTime 和 format 必须设置一样的格式.
format: "dd:hh:mm:ss",
startTime: "01:00:00:00",
digitImages: 6,
digitWidth: 53,
digitHeight: 77,
timerEnd: function() {},
image: "digits.png"
};
//digits数字对象(HTML元素)数组,interval定时器变量
var digits = [],
interval;
// 创建时钟
var createDigits = function(where) {
var c = 0; //startTime中当前字符
options.startTime = options.startTime.split('');
options.format = options.format.split('');
//循环startTime中的所有字符
for (var i = 0; i < options.startTime.length; i++) {
//如果是数字的话
if (parseInt(options.startTime[i]) >= 0) {
//创建HTML对象(elem)并设置CSS的高度宽度浮动
elem = $('<div id="cnt_' + i + '" class="cntDigit" />').css({
height: options.digitHeight * options.digitImages * 10,
float: 'left',
background: 'url(\'' + options.image + '\')',
options.digitWidth
});
digits.push(elem); //将elem压进digits数组
margin(c, -((parseInt(options.startTime[i]) * options.digitHeight * options.digitImages))); //设置elem的margin-top值,c是当前字符的序号,代表dd:hh:mm:ss中的第几位,当前的数字*数字的高度*一个数字由几张图片组成
digits[c].__max = 9; //设置元素的最大值为9
//通过格式设置元素最大值
switch (options.format[i]) {
//设置小时的最大值
case 'h':
digits[c].__max = (c % 2 == 0) ? 2 : 9;
if (c % 2 == 0) digits[c].__condmax = 4;
break;
//设置天数的最大值
case 'd':
digits[c].__max = 2;
break;
//设置分钟跟秒的最大值
case 'm':
case 's':
digits[c].__max = (c % 2 == 0) ? 5 : 9; //两位数,c%2==0代表前面那位最大值为5,c%2!=0代表后面那位最大值是9,例如59秒
}++c; //当前元素序号自加
} else
//如果不是数字,则按照日期格式中的字符创建元素分隔符例如dd:mm:ss则按照“:”创建;或者dd天hh小时则按照xx天xx小时创建
elem = $('<div class="cntSeparator"/>').css({
float: 'left'
}).text(options.startTime[i]);
//添加HTML元素
where.append(elem);
}
};
// 通过传过来的c设置或者取得digits中元素的margin-top值
var margin = function(elem, val) {
//如果传了val的话则设置
if (val !== undefined) return digits[elem].css({
'marginTop': val + 'px'
});
//如果没传val则返回
return parseInt(digits[elem].css('marginTop').replace('px', ''));
};
//设置移动动画
var moveStep = function(elem) {
digits[elem]._digitInitial = -(digits[elem].__max * options.digitHeight * options.digitImages); //数字最大的margin-top值
//执行运动函数
return function _move() {
mtop = margin(elem) + options.digitHeight; //获得元素的起始margin-top值
//如果起始值等于数字的高度
if (mtop == options.digitHeight) {
//设置元素的margin-top值为数字最大的marign-top值
margin(elem, digits[elem]._digitInitial);
//从最后一位(最右面)开始,如果数字大于0则调用递归显示前一位数字
if (elem > 0) moveStep(elem - 1)();
//否则如果数字全是0的话
else {
//清除定时器
clearInterval(interval);
//设置数字全为0
for (var i = 0; i < digits.length; i++) margin(i, 0);
//调用回调函数
options.timerEnd();
return;
}
//如果有数字(elem>0)并且有数字最大值(digits[elem].__condmax !== undefined)并且数字的最大margin-top值等于当前的margin-top则说明一个数字翻页动画完毕
if ((elem > 0) && (digits[elem].__condmax !== undefined) && (digits[elem - 1]._digitInitial == margin(elem - 1)))
//设置当前数字的margin-top值为最大margin-top值
margin(elem, -(digits[elem].__condmax * options.digitHeight * options.digitImages));
return;
}
margin(elem, mtop); //设置元素的margin-top值
//如果当前的数字元素不为0
if (margin(elem) / options.digitHeight % options.digitImages != 0)
//按照参数设置中的stepTime多少时间后执行运动动画
setTimeout(_move, options.stepTime);
//如果margin-top等于0的话,说明在图片的最上面
if (mtop == 0) digits[elem].__ismax = true;
}
};
$.extend(options, userOptions); //拷贝用户设置的参数
this.css({
height: options.digitHeight,
overflow: 'hidden'
}); //按照用户设置的高度设置数字高度
createDigits(this); //创建数字对象
interval = setInterval(moveStep(digits.length - 1), 1000); //创建定时器并调用运动函数
};