webapp之滑动组件(基于zepto)

一直都没有封装过一套移动web下的滑动组件,正巧今天公司没事,就闲下来写了一个半成品,称之为半成品是因为,循环效果暂时还没有添加。

;
(function($) {
    $.fn.slider = function(opts) {
        this.each(function() {
            init.call(this, opts);
        });
        return this;
    };

    function init(opts) {
        var defaults = {
            cont: this,
            contWidth: false, //容器宽度,默认屏幕宽
            contHeight: false, //容器高度,默认屏幕高
            dots: false,
            loop: false,
            autoplay: false,
            spacing: 5000, //自动播放间隔时长
            ifAjax: false, //ajax传图生成html,默认false
            ajaxUrl: ‘‘, //当开启ajax后,需传入用以构建的json
            ifMiddle: false //是否开启图片垂直居中
        };
        var options = $.extend({}, defaults, opts);

        var index = 0, //图片索引
            cWidth = options.contWidth ? options.contWidth : $(window).width(), //容器宽度
            cHeight = options.contHeight ? options.contHeight : $(window).height(), //容器高度
            cScale = cWidth / cHeight,
            self = this,
            currentX = 0,
            slopeSwitch = true,
            defaultSwitch = true,
            startX, startY, endX, endY, offsetX, offsetY, startTime, endTime, autoTime;

        var utils = {
            render: function() { //如果给定json,则渲染
                var hm = ‘‘,
                    ele = options.ajaxUrl,
                    eleLen = ele.length,
                    h_li = $(‘li‘),
                    i = 0;
                for (; i < eleLen; i++) {
                    hm += ‘<li>‘ + ‘<img src="‘ + ele[i].img + ‘" data-width="‘ + ele[i].width + ‘" data-height="‘ + ele[i].height + ‘" /></li>‘
                }
                $(self).html(‘<ul>‘ + hm + ‘</ul>‘)
            },
            imgResize: function() { //重置图片,把超出限制宽(高)度的图片都缩小
                var imgOriginalWidth,
                    imgOriginalHeight,
                    imgScale,
                    imgNewWidth,
                    imgNewHeight,
                    _this = this;
                $(‘li‘, self).find(‘img‘).each(function(i) {
                    imgOriginalWidth = _this.getImgWidth($(this))
                    imgOriginalHeight = _this.getImgHeight($(this))
                    imgScale = imgOriginalWidth / imgOriginalHeight
                    if (imgScale >= cScale) { //利用长宽比,计算该用宽度限制还是长度限制
                        imgNewWidth = imgOriginalWidth >= cWidth ? cWidth : imgOriginalWidth
                        $(this).attr(‘width‘, imgNewWidth)
                        $(this).attr(‘height‘, imgNewWidth / imgScale) //这里的高度一定要赋值,否则高度居中的时候获取不到值
                    } else {
                        imgNewHeight = imgOriginalHeight >= cHeight ? cHeight : imgOriginalHeight
                        $(this).attr(‘height‘, imgNewHeight)
                    }
                    $(this).parent().width(cWidth)
                    // console.log(imgScale, cScale)
                });
                if (options.ifMiddle) {
                    this.setImgMiddle()
                }
                this.setUlWidth()
            },
            setImgMiddle: function() {
                var _this = this,
                    wHeight = $(window).height(),
                    imgHeight, offsetHeight;
                $(‘li‘, self).find(‘img‘).each(function(i) {
                    imgHeight = $(this).height()
                    offsetHeight = wHeight - imgHeight
                    $(this).css(‘margin-top‘, offsetHeight / 2)
                })
            },
            getImgWidth: function(pic) {
                return pic.attr(‘data-width‘)
            },
            getImgHeight: function(pic) {
                return pic.attr(‘data-height‘)
            },
            setUlWidth: function() {
                var len = this.getElementNum();
                $(self).find(‘ul‘).width(cWidth * len)
            },
            getElementNum: function() {
                return $(self).find(‘li‘).size()
            },
            setAutoplay: function() {
                var _this = this
                if (options.autoplay) {
                    autoTime = setInterval(function() {
                        _this.goToIndex(1)
                    }, options.spacing)
                }
            },
            clearAutoplay: function() {
                var _this = this
                if (options.autoplay) {
                    clearInterval(autoTime)
                }
            },
            dotsRender: function() {
                var len = this.getElementNum(),
                    lists = ‘‘,
                    i = 0;
                for (; i < len; i++) {
                    lists += ‘<span>‘ + (i + 1) + ‘</span>‘
                }
                $(self).append(‘<div class="dots">‘ + lists + ‘</div>‘)
                this.dotsOn(0)
            },
            dotsOn: function(i) {
                var $dots = $(‘.dots‘, self).find(‘span‘)
                $dots.removeClass(‘cur‘)    
                $dots.eq(i).addClass(‘cur‘)
            },
            bindEvents: function() {
                var _this = this,
                    slideEle = $(self).find(‘ul‘);
                slideEle.on(‘touchstart‘, _this.touchStart)
                slideEle.on(‘touchmove‘, _this.touchMove)
                slideEle.on(‘touchend‘, _this.touchEnd)
                this.setAutoplay()
            },
            touchStart: function(e) {
                var slideEle = $(self).find(‘ul‘),
                    nowTime = new Date();
                slopeSwitch = true;
                defaultSwitch = true;
                startTime = nowTime.getTime()
                startX = e.touches[0].pageX
                startY = e.touches[0].pageY
                slideEle.css(‘transition‘, ‘-webkit-transform 0ms ease-out‘)
                utils.clearAutoplay()
            },
            touchMove: function(e) {
                var arrX = []
                var slope = (startX - e.touches[0].pageX) / (startY - e.touches[0].pageY)
                if (defaultSwitch) { //如果判定已经为浏览器默认滚动,则跳过流程
                    if (Math.abs(slope) < 0.8 && slopeSwitch) { //slopeSwitch控制当判定为图片轮播时,slope判定失效
                        defaultSwitch = false
                    } else {
                        slopeSwitch = false
                        var slideEle = $(self).find(‘ul‘)
                        offsetX = e.touches[0].pageX - startX
                        slideEle.css(‘transform‘, ‘translate3d(‘ + (currentX + offsetX) + ‘px, 0,0)‘)
                        e.preventDefault()
                    }
                }
                // console.log(Math.abs(slope))
            },
            touchEnd: function(e) {
                if (!defaultSwitch) {
                    return false
                }
                var nowTime = new Date(),
                    duration = 0;
                endTime = nowTime.getTime()
                duration = endTime - startTime
                if (duration > 300) { //手指拨的慢
                    if (Math.abs(offsetX) >= cWidth / 2) {
                        if (offsetX < 0) {
                            utils.goToIndex(1)
                        }
                        if (offsetX > 0) {
                            utils.goToIndex(-1)
                        }
                    } else {
                        utils.goToIndex(0)
                    }
                } else { //手指划的快
                    if (offsetX < -50) {
                        utils.goToIndex(1)
                    } else if (offsetX > 50) {
                        utils.goToIndex(-1)
                    } else {
                        utils.goToIndex(0)
                    }
                }
                offsetX = 0 //当结束后,重置offsetX,避免影响后续流程
                utils.setAutoplay()
            },
            goToIndex: function(i) {
                var slideEle = $(self).find(‘ul‘),
                    len = this.getElementNum();
                currentX = 0;
                if (i > 0) {
                    index++
                    index = index >= len ? len - 1 : index
                } else if (i < 0) {
                    index--
                    index = index <= 0 ? 0 : index
                }
                currentX = -(cWidth * index)
                this.dotsOn(index)
                slideEle.css(‘transition‘, ‘-webkit-transform 150ms ease-out‘)
                slideEle.css(‘transform‘, ‘translate3d(‘ + currentX + ‘px, 0,0)‘)
            }
        };

        var initialize = (function() { //初始化
            if (options.ifAjax) {
                utils.render()
            }
            utils.imgResize()
            utils.bindEvents()
            if (options.dots) {
                utils.dotsRender()
            }
        })()
    }
})(Zepto)

其实移动端的滑动组件编写起来与电脑上的还是有很大差异的,对于手指滑动的角度问题,动画需要使用css3,还有手指快速滑动图片切换的效果等等,这些都是电脑上不会遇到的问题。由于添加了一个图片不论大小都能在content中自适应居中的效果,所以循环效果可能要晚点才能实现,另外还有一个边界时再拉动的一个减速效果,这个后期应该也会实现。等全部实现后,就详细说明下怎么实现一个滑动组件,以及会遇到的问题的处理。

ps: 要想写能用的滑动组件,千万别看慕课网的那个教程啊!!!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。