美文网首页
使用swiper + angular+jquery实现上下滑动的

使用swiper + angular+jquery实现上下滑动的

作者: Gemkey | 来源:发表于2017-12-09 13:42 被阅读32次

    使用angular1+swiper4 实现上下滑动的日历
    实现思路:
    当上下滑动时,使用jquery写入当前日期到日历上去,最初的想法是使用swiper的loop属性,来实现,但是实际使用下来之后发现体验并不好,并且会存在一些BUG,所以就改用VirtualSlide来实现.代码如下:

    html部分

    <div ng-controller="calendarController">
      <div class="swiper-container swiper-container-horizontal swiper-container-ios">
            <div class="swiper-wrapper">
            </div>
      </div>
    </div>
    

    js部分

    angular.module('app', []).controller('calendarController',function ($scope,$compile) {
        var currentIndex = 0;
        var compiledArray = [];// 已经被编译过的dom的index
        // 定义每个月的日历,最大是42个
        $scope.monthCalendar = new Array(42);
     
        var mySwiper = {};
        angular.element(document).ready(function () {
            var totalSlides = 1000; // 默认定义1000个slides
            var initialSlide = totalSlides / 2;
            mySwiper = new Swiper('.swiper-container', {
                slidesPerView: 1,
                initialSlide: initialSlide,
                spaceBetween: 30,
                direction: 'vertical',
                height: 600,
                virtual: {
                    slides: (function () {
                        var slides = [];
                        // 加载html
                        for (var i = 0; i < totalSlides; i += 1) {
                            var html = '<div lnk-slides class="weekday-container">\n' +
                                '                            <span ng-repeat="day in weekDays" ng-bind="day">\n' +
                                '                            </span>\n' +
                                '                        </div>\n' +
                                '                        <div class="day-item-container" ng-repeat="i in [0,1,2,3,4,5]">\n' +
                                '                            <span\n' +
                                '                                  class="day-item current-month-day" ng-click="selectCurrentDay($event)" ng-repeat="j in weekDays"></span>\n' +
                                '                        </div>';
    
                            slides.push(html);
                        }
                        return slides;
                    }())
                },
                on: {
                    init: function () {
                        // 当Swiper初始化完成后,将默认的slide编译后加入到数组中
                        compiledArray.push(this.realIndex);
                        $compile(this.slides[1])($scope);
                        $scope.$apply();
                    },
                },
            });
    
            // 当前选中slide的index
            // 用于控制上下滑动是否实际切换slide
            // 向上滑动
            mySwiper.on('slidePrevTransitionEnd', function () {
                if (currentIndex !== mySwiper.realIndex) {
                    currentIndex = mySwiper.realIndex;
                    // 未被angular编译的dom元素需要被编译后才能在angular的监听下
                    if (!compiledArray.contains(mySwiper.realIndex)) {
                        compiledArray.push(mySwiper.realIndex);
                        $compile(this.slides[1])($scope);
                        $scope.$apply();
                    }
                    $scope.currentSelectedDate = new Date($scope.currentSelectedDate.getFullYear(), $scope.currentSelectedDate.getMonth() - 1, $scope.currentSelectedDate.getDate());
                    $scope.getCalendar('prev', $scope.currentSelectedDate);
                }
            });
            // 向下滑动
            mySwiper.on('slideNextTransitionEnd', function () {
                // 已经切换了页签,则刷新日期及数据
                if (currentIndex !== mySwiper.realIndex) {
                    // 未被angular编译的dom元素需要被编译后才能在angular的监听下
                    if (!compiledArray.contains(mySwiper.realIndex)) {
                        compiledArray.push(mySwiper.realIndex);
                        $compile(this.slides[1])($scope);
                        $scope.$apply();
                    }
                    currentIndex = mySwiper.realIndex;
                    $scope.currentSelectedDate = new Date($scope.currentSelectedDate.getFullYear(), $scope.currentSelectedDate.getMonth() + 1, $scope.currentSelectedDate.getDate());
                    $scope.getCalendar('next', $scope.currentSelectedDate);
                }
            });
            // 加载完Swiper之后,默认显示今天的日期及数据
            $scope.getCalendar('today', $scope.currentSelectedDate);
        });
    
        /**
         * 创建日历数据
         */
        $scope.getCalendar = function (direction, currentSelectedMonthDate) {
            var year = ''; // 年份
            var month = '';// 月份
            // 用于存储数据的对象
            $scope.monthCalendar = [];
            // 获取年份和月份
            year = currentSelectedMonthDate.getFullYear();
            month = currentSelectedMonthDate.getMonth() + 1;
            // 获取当月的第一天
            var firstDate = new Date(year, month - 1, 1);
            // 获取当前slide下的子对象个数,默认是有42个
            var spans = $('.swiper-slide.swiper-slide-active .day-item-container .day-item');
            for (var i = 0; i < spans.length; i++) {
                // 获取个子对象对应的日期
                var date = new Date(year, month - 1, i + 1 - firstDate.getDay());
                var spanItem = $(spans[i]);
                // 非当月,则移除class
                if (date.getMonth() !== month - 1) {
                    spanItem.removeClass('current-month-day');
                } else {
                    // 日期数据
                    var dateStr = dateFormat(date);
                    // 如果是今天,则标红
                    if (dateStr === dateFormat(new Date())) {
                        spanItem.addClass('today');
                    }
                }
                $scope.monthCalendar[i] = dateStr;
                // 点击时需要用到的数据,所以直接加到属性上去
                spanItem.attr('current-date-data', dateStr);
                spans[i].innerText = dateFormat(date, 'MM-dd');
            }
        };
        $scope.selectCurrentDay = function ($event) {
            var target = $event.target;
            console.log($(target).attr('current-date-data'));
        };
    
        // 设置slides个数,用两个做循环,如果只使用一个,无法向下滚,估计是BUG..
        $scope.slides = [1, 2];
        // 默认初始化选中的日期为今天
        $scope.currentSelectedDate = new Date();
        $scope.weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    
    
    
        /**
         * 日期对象转为日期字符串
         * @param date 需要格式化的日期对象
         * @param sFormat 输出格式,默认为yyyy-MM-dd                         年:y,月:M,日:d,时:h,分:m,秒:s
         * @example  dateFormat(new Date())                                "2017-02-28"
         * @example  dateFormat(new Date(),'yyyy-MM-dd')                   "2017-02-28"
         * @example  dateFormat(new Date(),'yyyy-MM-dd hh:mm:ss')         "2017-02-28 09:24:00"
         * @example  dateFormat(new Date(),'hh:mm')                       "09:24"
         * @example  dateFormat(new Date(),'yyyy-MM-ddThh:mm:ss+08:00')   "2017-02-28T09:24:00+08:00"
         * @returns {string}
         */
        function dateFormat(date, sFormat) {
            if(isEmpty(sFormat)){
                sFormat = 'yyyy-MM-dd'
            }
            var time = {
                Year: 0,
                TYear: '0',
                Month: 0,
                TMonth: '0',
                Day: 0,
                TDay: '0',
                Hour: 0,
                THour: '0',
                hour: 0,
                Thour: '0',
                Minute: 0,
                TMinute: '0',
                Second: 0,
                TSecond: '0',
                Millisecond: 0
            };
            time.Year = date.getFullYear();
            time.TYear = String(time.Year).substr(2);
            time.Month = date.getMonth() + 1;
            time.TMonth = time.Month < 10 ? "0" + time.Month : String(time.Month);
            time.Day = date.getDate();
            time.TDay = time.Day < 10 ? "0" + time.Day : String(time.Day);
            time.Hour = date.getHours();
            time.THour = time.Hour < 10 ? "0" + time.Hour : String(time.Hour);
            time.hour = time.Hour < 13 ? time.Hour : time.Hour - 12;
            time.Thour = time.hour < 10 ? "0" + time.hour : String(time.hour);
            time.Minute = date.getMinutes();
            time.TMinute = time.Minute < 10 ? "0" + time.Minute : String(time.Minute);
            time.Second = date.getSeconds();
            time.TSecond = time.Second < 10 ? "0" + time.Second : String(time.Second);
            time.Millisecond = date.getMilliseconds();
    
            return sFormat.replace(/yyyy/ig, String(time.Year))
                .replace(/yyy/ig, String(time.Year))
                .replace(/yy/ig, time.TYear)
                .replace(/y/ig, time.TYear)
    
                .replace(/MM/g, time.TMonth)
                .replace(/M/g, String(time.Month))
    
                .replace(/dd/ig, time.TDay)
                .replace(/d/ig, String(time.Day))
    
                .replace(/HH/g, time.THour)
                .replace(/H/g, String(time.Hour))
                .replace(/hh/g, time.Thour)
                .replace(/h/g, String(time.hour))
    
                .replace(/mm/g, time.TMinute)
                .replace(/m/g, String(time.Minute))
                .replace(/ss/ig, time.TSecond)
                .replace(/s/ig, String(time.Second))
                .replace(/fff/ig, String(time.Millisecond))
        }
    
        function isEmpty(v) {
            if (v == null) {
                return true;
            }
            if (v == undefined) {
                return true;
            }
            if (v == "") {
                return true;
            }
            if (typeof v == "undefined") {
                return true;
            }
            switch (typeof v) {
                case 'date':
                    return true;
                case 'undefined' :
                    return true;
                case 'string' :
                    if (v.trim().length === 0)
                        return true;
                    break;
                case 'boolean' :
                    if (!v)
                        return true;
                    break;
                case 'number' :
                    if (0 === v)
                        return true;
                    break;
                case 'object' :
                    if (null === v) {
                        return true;
                    }
                    else if (undefined !== v.length && v.length === 0) {
                        return true;
                    }
                    else {
                        return false;
                    }
                    break;
            }
            return false;
        };
    });
    
    Array.prototype.contains = function (obj) {
        var index = this.length;
        while (index--) {
            if (this[index] === obj) {
                return true;
            }
        }
        return false;
    }
    

    需要注意几点:
    1.这里创建swiper对象,需要在angular的dom加载完成后再做,否则会报错
    2.slide的高度现在是直接定成600px,在有些情况下是不合适的,所以可以根据屏幕宽高来动态设置,这里就不加了

    css部分,用的是scss

    .swiper-container {
        height: 100%;
      }
      .swiper-slide {
        text-align: center;
        font-size: 18px;
        background: #fff;
        width: 100%;
        height: 80%;
        flex-wrap: wrap;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 10px;
        .weekday-container{
          width: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          span{
            color: red;
          }
        }
        .day-item-container{
          width: 100%;
          display: flex;
          align-items: center;
          justify-content: center;
          .day-item{
    
          }
        }
        span{
          display: inline-block;
          width: calc(100% /7);
          color:gray;
        }
        .today{
          color: red !important;
        }
        .current-month-day{
          color: green;
        }
      }
    

    这个现在还存在着一点问题,就是未被加载过的VirtualSlide 会出现头部空白部分,后面研究看看能不能解决
    最终效果:

    calendar.gif

    相关文章

      网友评论

          本文标题:使用swiper + angular+jquery实现上下滑动的

          本文链接:https://www.haomeiwen.com/subject/qqwqbxtx.html