日历实现

Posted 心素如简,人淡如菊。

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日历实现相关的知识,希望对你有一定的参考价值。

 

 日历要实现下面两种效果,图一是周数据,左右滑动切换不同周的数据。下拉后,切换成月数据即图二。在月数据视图下,上滑切换成周数据。

 

 

 

 

/**
 * 日历插件 依赖zepto.js
 * 使用:
 * Calendar.initialize(\'.calendar-zone\');
            Calendar.fBind("dateChange", function(date) { //日历上选中的日期
                self.selectedDate = date;
                
            });
 */
define(function(require,exports,module){
    var Swipe = require(\'./swipe\');
    var Calendar = {
        /**
         * 初始化日历数据
         * @param    {[type]}                 selector 日历数据填充到哪个元素
         * @param    {[type]}                 type    week month 生成周日历 or 月日历
         */
        _config:{
            MONTH:"month",  //生成一周数据还是一月数据
            WEEK:"week",
            SlideTime:400   //动画效果的时间
        },
        initialize: function(selector){
            this.type = this._config.WEEK;
            this.selector = selector;
            var title_calendar = this.fGetCalendarTitle();
            $(selector).html(title_calendar);

            this.initProp();
            this.fRender(this.CurYear,this.CurMonth,this.CurDay);
        },
        initProp: function(){
            var d = new Date();
            this.CurYear = d.getFullYear();
            this.CurMonth = d.getMonth();
            this.CurDay = d.getDate();
            this.MonthData = this.fGetCalendarData_month(this.CurYear,this.CurMonth);
            this.WeekIndex = this.fCalculatePos(this.MonthData,this.CurYear,this.CurMonth,this.CurDay);
            this.MaxWeek = this.MonthData.length / 7;
            this.eventDate = [];   //有事件的日期
            this.callback = {};  // {dateChange:callback}
            var m = this.CurMonth +1;
            this.selectedDate = this.CurYear+"-"+m+"-"+this.CurDay;  //日历上选中的日期
            this._width = $(".calendar-content-pas").width();   //日历控件宽度
            this._initTop = -$(".calendar-title-pas").height()*(this.MaxWeek+1);
        },
        fGetCalendarTitle: function(){
            var title = "<ul class=\'calendar-title-pas calendar-pas\'><li>日</li><li>一</li><li>二</li><li>三</li><li>四</li><li>五</li><li>六</li></ul><div class=\'calendar-content-pas\'></div>";
            return title;
        },
        fRender: function(year,month,day){
            var tpl = this.fLoadTemplate(year,month,day);
             $(\'.calendar-content-pas\').html(tpl);
            if(this.type == this._config.WEEK){
                this.weekHeight = $(".calendar-week-pas").height();
            }
            this._fBindEvt();
        },
        /**
         * 日历模板数据 month 0-11, day 1-31
         */
        fLoadTemplate: function(year,month,day){
            var dataType = this.type, tpl ="";
            var showMonth = this.CurMonth + 1;
            var data = this.MonthData;
            if(dataType == this._config.MONTH){
                tpl = "<div class=\'calendar-month-div\' style=margin-top:"+ this._initTop+"px" +">"+"<p class=\'calendar-showmonth-pas\'>"+this.fTransfNum2Upper(showMonth)+"月</p><ul class=\'calendar-month-pas calendar-pas\'>";
                var lis = this.fGetLiTpl(data,year,month);
                tpl = tpl + lis +"</ul></div>";
            }else if(dataType == this._config.WEEK){
                var left = -(this.WeekIndex-1)*this._width+"px";
                var ul_wid = (this._width / 7) * data.length + \'px\';
                tpl = "<ul class=\'calendar-week-pas calendar-pas\' style=width:"+ ul_wid +";margin-left:"+left+ ">";
                tpl = tpl + this.fGetLiTpl(data,year,month)+"</ul>";
            }
            return tpl;
        },
        //填充每一行的数据
        fGetLiTpl: function(data,year,month){
            var li_tpl = \'\';
            for(var i=0,len=data.length;i<len;i++){
                var rec = data[i];
                var fillYear = rec.year,fillMonth = rec.month, fillDay = rec.day;
                var isToday = this.fIsCurrentDay(fillYear,fillMonth,fillDay);
                var activeDay = isToday ? fillDay: null;
                var m = fillMonth + 1;
                var attr =  fillYear+"-"+m+"-"+ fillDay;
                var classItem = fillMonth == this.CurMonth ? \'\' :\'unvisibleItem\';
                classItem += fillDay == activeDay ? " activeDay" : " normalDay";
                fillDay = isToday ? "今" : fillDay;
                var li_wid = $(".calendar-content-pas").width() / 7 +"px";
                li_tpl += "<li class=\'"+classItem+"\'"+ " calendar-date=\'"+attr+"\'"+" style=width:"+li_wid+"><a href=\'javascript:void(0)\'>"+fillDay+"<i></i></a></li>";
            }
            return li_tpl;
        },
        _fBindEvt: function(){
            var self = this;
            $(".calendar-content-pas li ").on("click",function(){
                var clickObj = this;
                self._fSelectDate(clickObj);
            });
            var swipeObj = new Swipe(".calendar-week-pas");
            swipeObj.bind("swipeLeft",function(){
                self.fGoNextWeek();
            });
            swipeObj.bind("swipeRight",function(){
                self.fGoPrevWeek();
            });
            swipeObj.bind("swipeDown",function(){
                 if(self.type==self._config.MONTH){ //已经是月数据
                    return;
                }
                console.log("swipeDown...显示月数据");
                self.fShowMonthData();
                if(typeof self.callback.slideDown == \'function\'){
                    self.callback.slideDown();
                }
            });
            var monthSwipe = new Swipe(".calendar-month-pas");
            monthSwipe.bind("swipeUp",function(){               
                if(self.type==self._config.WEEK){ //已经是周数据  多次上滑操作 只更新一次
                    return;
                }
                console.log("swipeUp...显示周数据");
                self.fShowWeekData();
            });
        },
        //滑动到上一周数据
        fGoPrevWeek: function(){
            if(this.WeekIndex <= 1){ return; }
            this.WeekIndex--;
            var li_wid = this._width / 7;
            var left = -(this.WeekIndex-1)*(li_wid*7);
            this.fSlideEffect(".calendar-week-pas","margin-left");
            $(".calendar-week-pas").css("margin-left",left+"px");
        },
        fGoNextWeek: function(){
            if(this.WeekIndex >= this.MaxWeek){ return; }
            this.WeekIndex++;
            var li_wid = this._width / 7;
            var left = -(this.WeekIndex-1)*(li_wid*7);
            this.fSlideEffect(".calendar-week-pas","margin-left");
            $(".calendar-week-pas").css("margin-left",left+"px");
        },
        //下拉 显示月历
        fShowMonthData: function(){
            this.type = this._config.MONTH;
            this.fUpdateCalendar(this.CurYear,this.CurMonth,this.CurDay);
            var top = -$(".calendar-month-div").height()+"px";
            $(".calendar-month-div").css("margin-top",top);
            this.fSlideEffect(".calendar-month-div","margin-top");
            $(".calendar-month-div").css("margin-top","0");
        },
        //周 日历
        fShowWeekData: function(){
            this.type = this._config.WEEK;
            var arr = this.selectedDate.split("-");
            var year = parseInt(arr[0]), month = parseInt(arr[1])-1,day = parseInt(arr[2]);
            this.WeekIndex = this.fCalculatePos(this.MonthData,year,month,day);
            var self = this;
           var top = -($(".calendar-month-div").height()-this.weekHeight)+"px";
           $(".calendar-month-div").css("margin-top",top);
            var time = this._config.SlideTime;
            setTimeout(function(){
                 $(".calendar-month-div").remove();
                 console.log(\'slide end.\');
                 console.log(\'当前类型\',self.type);
                 if(self.type==self._config.WEEK){
                     self.fUpdateCalendar(year,month,day);
                 }              
            },time);
        },
        //更新日历
        fUpdateCalendar: function(year,month,day){
            console.log(\'更新日历,日历类型\',this.type);
            this.fRender(year,month,day);
            this.fRenderEventDate();
            this.fRenderSelected(this.selectedDate);
        },
        //在某个元素上使用滑动效果
        fSlideEffect: function(element,attr){
            var time = this._config.SlideTime;
            var style = {
                    \'-webkit-transition\':attr +" "+time+\'ms\',
                    \'transition\':attr + " "+time+\'ms\',
                    \'-webkit-backface-visibility\': \'hidden\'
                };
            $(element).css(style);
        },
        //绑定自定义事件  对外暴露
        fBind: function(evtName,callback){
            if(evtName==\'dateChange\'){
                this.callback.dateChange = callback;
            }else if(evtName==\'slideDown\'){
                this.callback.slideDown = callback;
            }
        },
        //计算周 的位置
        fCalculatePos: function(data,year,month,day){
            var weekIndex = 1;
            for(var i=0,len=data.length;i<len;i++){
                var rec = data[i];
                var fillYear = rec.year,fillMonth = rec.month, fillDay = rec.day;
                if(fillYear==year && fillMonth==month && fillDay==day){
                    weekIndex = Math.ceil( (i+1) / 7);
                }
            }
            return weekIndex;
        },
        //选择时间
        _fSelectDate: function(clickObj){
            if($(clickObj).hasClass(\'unvisibleItem\')){ return;}
            var date = $(clickObj).attr(\'calendar-date\');
            if(this.selectedDate != date){
                this.selectedDate = date;
                this.fRenderSelected(date);
                if(typeof this.callback.dateChange ==\'function\'){
                    this.callback.dateChange(date);
                }
            }
        },
        //渲染选中日期
        fRenderSelected: function(selectedDate){
            var self = this;
            $(".calendar-content-pas li").each(function(){
                var date = $(this).attr("calendar-date");
                var showday = date.split("-")[2];
                if($(this).hasClass(\'activeDay\') && selectedDate != date){
                    $(this).removeClass(\'activeDay\');
                    $(this).children(\'a\').eq(0).html(showday+"<i></i>");
                }
                if(selectedDate == date){
                    $(this).addClass(\'activeDay\');
                    var arr = date.split("-"),year = arr[0], month = arr[1]-1,day = arr[2];
                    var isCurrentDay = self.fIsCurrentDay(year,month,day);
                    if(isCurrentDay){
                        $(this).children(\'a\').eq(0).html("今<i></i>");
                    }
                }
            });
        },
        //获取日历模板  一个月的数据信息
        fGetCalendarData_month: function(year,month){
            var monthInfo = this.fGetMonthInfo(year,month);
            var firstDay = monthInfo.firstDay;
            var lastDay = monthInfo.lastDay;
            var totalDays = monthInfo.totalDays;
            var fillData = []; //{year:,month:0-11,day:1-31}
            var prevData = firstDay!==0 ? this._fGetPrevData(firstDay,year,month) : [];
            fillData = fillData.concat(prevData);
            for(var k=1;k<totalDays+1;k++){
                fillData.push({year:year,month:month,day:k});
            }
            var nextData = lastDay!==6 ? this._fGetNextData(lastDay,year,month) : [];
            fillData = fillData.concat(nextData);
            return fillData;
        },
        // 月日历模板 不足的用上一个月的补充
        _fGetPrevData: function(firstDay,year,month){
            var prevData = [];
            var lastMonth_info = this.fGetDaysOfPrevMonth(year,month);
            var totalDays_last = lastMonth_info.totalDays;
            for(var i=firstDay-1;i>=0;i--){
                var _prevDay = totalDays_last - i;
                var obj = {year:lastMonth_info.year,month:lastMonth_info.month,day:_prevDay};
                prevData.push(obj);
            }
            return prevData;
        },
        _fGetNextData: function(lastDay,year,month){
            var nextData = [];
            var nextMonth_info = this.fGetDaysOfNextMonth(year,month);
            for(var j=1;j<7-lastDay;j++){  //最后一天 之后的 没有数据的
                var obj = {year:nextMonth_info.year,month:nextMonth_info.month,day:j};
                nextData.push(obj);
            }
            return nextData;
        },
        //有事件的日期下方加点号 dateArr[\'20161125\',\'\',....]
        fAddEvtCircle: function(dateArr){
            this.eventDate = dateArr;
            this.fRenderEventDate();
        },
        //有事件的日期 加小圆点
        fRenderEventDate: function(){
            var dateArr = this.eventDate;
            $(".calendar-content-pas li").each(function(){
                var date = $(this).attr("calendar-date");
                if($.inArray(date, dateArr)!=-1){
                    $(this).addClass(\'symbol\');
                }
            });
        },
        /**
         * 获取某一个月的天数、第一天 最后一天周几   new Date(xxxx,xx,0) 0 即返回上一个月的最后一天
         * @param    {Number}                 year
         * @param    {Number}                 month  月份数 0-11
         */
        fGetDaysOfMonth: function(year,month){
            if(month >11 || month < 0){ return;}
            var d = new Date(year,month+1,0);  //上一个月的最后一天
            var days = d.getDate();  //天数
            return days;
        },
        //获取上一个月的天数
        fGetDaysOfPrevMonth: function(year,month){
            if(month===0){
                year = year -1;  //获取上一年的最后一个月
                month = 11;
            }else{
                month = month - 1;
            }
            var days = this.fGetDaysOfMonth(year,month);
            return {totalDays:days,year:year,month:month};
        },
        // 获取下一个月的天数
        fGetDaysOfNextMonth: function(year,month){
            if(month===11){
                year = year + 1;
                month = 0;
            }else{
                month = month + 1;
            }
            var days = this.fGetDaysOfMonth(year,month);
             return {totalDays:days,year:year,month:month};
        },
        //获取月份的信息 总天数,第一天 最后一天周几
        fGetMonthInfo: function(year,month){
            if(month >11 || month < 0){ return;}
            var d = new Date(year,month+1,0);  //上一个月的最后一天
            var days = d.getDate();  //天数
            var lastDay = d.getDay();
            var firstDay = this.fGetWeekOfDay(year,month,1);  //第一天周几
            return {firstDay:firstDay,lastDay:lastDay,totalDays:days};
        },
       // 获取某一天 周几  month  0-11    day  1-31
        fGetWeekOfDay: function(year,month,day){
            if(day > 31 || day < 1){ return; }
            var d = new Date(year,month,day);
            return d.getDay();  //星期几
        },
        //判断是否是当前日期
        fIsCurrentDay: function(year,month,day){
            var d = new Date();
            return d.getFullYear() == year && d.getMonth() == month && day == d.getDate();
        },
       fTransfNum2Upper : function(i){
            i = i.toString();
            var NumberArr = ["","一","二","三","四","五","六","七","八","九","十"];
            var result = i <= 10 ? NumberArr[i] : "十"+NumberArr[i.split("")[1]];
            return result;
        }
    };
    module.exports = Calendar;
});

 

以上是关于日历实现的主要内容,如果未能解决你的问题,请参考以下文章

实现自定义的日历控件

Android实现简单日历

vue实现日历

java 日历代码实现

Excel日历控件实现下拉选取日期含VB代码实现

C++实现的一个打印日历程序