美文网首页
使用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