app.directive("CountDown",['$interval',function ($interval) {
return {
restrict: "E",
replace: true,
template: '<span>' +
//1还没开始阶段
//1-0 今天
'<span ng-if="returnState.period==1 && returnState.gap.natureDay==0" ng-show="options.showWhen.indexOf(100)!=-1">今天<span class="timeTick">{{ returnState.date.hour}}</span> : <span class="timeTick">{{returnState.date.minute}} </span></span>' +
//1-1 明天
'<span ng-if="returnState.period==1 && returnState.gap.natureDay==1" ng-show="options.showWhen.indexOf(101)!=-1">明天<span class="timeTick"> {{returnState.date.hour}}</span> : <span class="timeTick">{{returnState.date.minute}}</span></span>' +
// 1-2 后天
'<span ng-if="returnState.period==1 && returnState.gap.natureDay==2" ng-show="options.showWhen.indexOf(102)!=-1">后天<span class="timeTick"> {{returnState.date.hour}}</span> : <span class="timeTick">{{returnState.date.minute}}</span></span>' +
//1-3 没有汉字能表达,除非你说几天后
'<span ng-if="returnState.period==1 && returnState.gap.natureDay!=0&&returnState.gap.natureDay!=1&&returnState.gap.natureDay!=2" ng-show="options.showWhen.indexOf(99)!=-1"><span class="timeTick"> {{returnState.date.natureMonth}}</span> 月 <span class="timeTick">{{returnState.date.date}}</span>日</span>' +
// 2 预倒计时和单时间倒计时
'<span ng-if="returnState.period==2" ng-show="options.showWhen.indexOf(200)!=-1" >' +
'<span ng-if="returnState.gap.days!=0"><span class="timeTick"> {{returnState.gap.days}}</span> 天</span>'+
'<span class="timeTick"> {{returnState.gap.hours}}</span> : ' +
'<span class="timeTick">{{returnState.gap.minutes}} </span> : ' +
'<span class="timeTick">{{returnState.gap.seconds}}</span>' +
'</span>'+
// 双时间区间中倒计时
'<span ng-if="returnState.period==3" ng-show="options.showWhen.indexOf(300)!=-1" >' +
'<span ng-if="returnState.gap.days!=0"><span class="timeTick"> {{returnState.gap.days}}</span> 天</span>'+
'<span class="timeTick"> {{returnState.gap.hours}}</span> : ' +
'<span class="timeTick">{{returnState.gap.minutes}}</span> : ' +
'<span class="timeTick">{{returnState.gap.seconds}} </span>' +
'</span>'+
// 结束了
'</span>',
scope: {
options: "=", //传入选项
returnState: "=" //返回选项
},
link: function (scope, ele, attr) {
var timer; 定时器
// 这里用watch是因为有可能是在指令解析完毕后动态改变options,而此时指令惰性地不去更新 options导致无法发挥作用。
scope.$watch('options',function(options){
if(!options) return console.log("倒计时指令缺少必要参数");
var opt={};
/***参数过滤****/
opt.startDate= validateDate(options.startDate); //开始时间,必要参数。可传入数字或者数字字符串,含义为时间戳。
opt.endDate= validateDate(options.endDate); // 结束时间,可选参数。同上。
opt.preCountMs= options.preCountMs || 2*3600*1000; //双时间的时候可以预倒计时。
opt.showWhen=options.endDate?(options.showWhen||[300]):(options.showWhen||[200]); // 在什么阶段显示。可能值:99表示没开始要显示x月x日,100表示要显示今天x点x分,101表示要显示明天x点x分,102表示要显示后天x点x分,200表示要显示预计倒计时的时候显示,300表示区间倒计时要显示。400结束了,传或者不传都不会显示。
opt.preFn = validateFn(options.preFn); //表示预倒计时开始那刻要执行的函数。
opt.startFn = validateFn(options.startFn); //表示预开始那刻要执行的函数。
opt.endFn = validateFn(options.endFn); //表示预结束那刻要执行的函数。
//单时间倒计时。
if(!opt.endDate){
timer=$interval(function(){
if(opt.startDate>new Date().getTime()){
scope.returnState={
period: 2,
gap:transformDate(opt.startDate).gap
};
scope.reloadWhenStart=true;
}
else{
if(scope.reloadWhenStart) scope.options.startFn();
scope.returnState={
period: 4,
date:transformDate(options.startDate).date
}
}
},1000)
}
// 双时间倒计时。
else{
timer=$interval(function () {
scope.returnState= shortCut(opt);
if(scope.returnState.period==1&&scope.returnState.gap.natureDay==0) scope.reloadWhenPreCount=true;
if(scope.returnState.period==2) scope.reloadWhenStart=true;
if(scope.returnState.period==3) scope.reloadWhenEnd=true;
if(scope.reloadWhenPreCount&&scope.returnState.period==2) opt.preFn();
if(scope.reloadWhenStart&&scope.returnState.period==3) opt.startFn();
if(scope.reloadWhenEnd&&scope.returnState.period==4) opt.endFn();
},1000)
}
})
scope.$on('$destroy',function () {
$interval.cancel(timer);
});
function validateDate(dateTime){
dateTime= parseInt(dateTime);
if (typeof dateTime != "number") return console.error ("需要整数作为参数");
dateTime=parseInt(dateTime*Math.pow(10,13-dateTime.toString ().length));
return dateTime;
}
function validateFn(fn){
if (!fn || typeof fn !="function") return function(){window.location.reload()}
else return fn;
};
function period (options) {
if (typeof options != "object" || typeof options.length == "number") {
console.error ("countDown传入的参数错误。\n应该是一个对象,key有startDate(起始时间戳), endDate(结束时间戳), preCountMs(预倒计时阈值,单位为毫秒)");
console.log ("返回period为整数类型,1表示未开始且未进入倒计时,2表示进入开始倒计时,3表示结束倒计时,4表示已经结束");
return
}
options.startDate=validateDate(options.startDate);
options.endDate=validateDate(options.endDate);
options.preCountMs=options.preCountMs || 2*3600*1000;
if(options.startDate>options.endDate) return console.error("时间起始值矛盾");
var now = new Date();
var nowTime= now.getTime();
if (nowTime>options.endDate) return 4;
else if (options.endDate>=nowTime && nowTime>=options.startDate) return 3;
else if (options.startDate>nowTime && nowTime> options.startDate-options.preCountMs) return 2;
else if (options.startDate-options.preCountMs>=nowTime) return 1;
else console.error("出错了,找少侠");
};
function transformDate (dateTime) {
dateTime = validateDate(dateTime);
var thisDate = new Date (dateTime);
var gap = {};
var now = new Date();
var zeroThisDateTime= new Date(thisDate.getFullYear(),thisDate.getMonth(),thisDate.getDate()).getTime();
var zeroNowDateTime= new Date(now.getFullYear(),now.getMonth(),now.getDate()).getTime();
var _toString= function (num) {
var str = num.toString();
return str.length==1?"0"+str:str;
};
gap.Ms=dateTime-now.getTime();
gap.days= _toString(parseInt(gap.Ms/(24*3600*1000)));
gap.hours= _toString(parseInt((gap.Ms-gap.days*24*3600*1000)/(3600*1000)));
gap.minutes=_toString(parseInt((gap.Ms-gap.days*24*3600*1000-gap.hours*3600*1000)/(60*1000)));
gap.seconds=_toString(parseInt((gap.Ms-gap.days*24*3600*1000-gap.hours*3600*1000-gap.minutes*60*1000)/1000));
gap.natureDay = _toString((zeroThisDateTime-zeroNowDateTime)/(24*3600*1000));
return {
date: {
year: thisDate.getFullYear (),
month: _toString(thisDate.getMonth ()),
natureMonth: _toString(thisDate.getMonth () + 1),
date: _toString(thisDate.getDate ()),
hour: _toString(thisDate.getHours ()),
minute: _toString(thisDate.getMinutes ()),
second: _toString(thisDate.getSeconds ())
},
gap: gap
}
};
function shortCut (options) {
var _period = period(options);
switch (_period){
case 1:
return {
period: 1,
gap: transformDate(options.startDate).gap,
date:transformDate(options.startDate).date
};
case 2:
return {
period:2,
gap:transformDate(options.startDate).gap
};
case 3:
return{
period:3,
gap: transformDate(options.endDate).gap
};
case 4:
return{
period: 4,
date:transformDate(options.startDate).date
}
}
}
}
}
}])
有问题请入群454796847交流