• webapp之滑动组件(基于zepto)


    一直都没有封装过一套移动web下的滑动组件,正巧今天公司没事,就闲下来写了一个... 

    ;
    (function($) {
        $.fn.slider = function(opts) {
            this.each(function() {
                init.call(this, opts);
            });
            return this;
        };
    
        function init(opts) {
            var defaults = {
                contWidth: false, //容器宽度,默认屏幕宽
                contHeight: false, //容器高度,默认屏幕高
                dots: false,
                loop: false,
                autoplay: false,
                lazyload: false, //是否开启图片懒加载,默认关闭
                spacing: 5000, //自动播放间隔时长
                aniTime: 200, //每帧动画时间
                ifAjax: false, //ajax传图生成html,默认false
                ajaxUrl: '', //当开启ajax后,需传入用以构建的json
                ifMiddle: false //是否开启图片垂直居中
            };
    
            var options = $.extend({}, defaults, opts);
    
            var index = 0, //图片索引
                loopIndex = 0, //循环是的索引
                prefix = '', //css前缀
                testEl = document.createElement('div'),
                vendors = {
                    Webkit: 'webkit',
                    Moz: '',
                    O: 'o'
                },
                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,
                eleNum = 1,
                loop = options.loop,
                startX, startY, offsetX, offsetY, startTime, endTime, autoTime;
    
            $.each(vendors, function(vendor) { //生成css前缀
                if (testEl.style[vendor + 'TransitionProperty'] !== undefined) {
                    prefix = '-' + vendor.toLowerCase() + '-'
                    return false
                }
            })
    
            var utils = {
                render: function() { //如果给定json,则渲染
                    var hm = '',
                        ele = options.ajaxUrl,
                        eleLen = ele.length,
                        h_li = $('li'),
                        picUrl = 'src',
                        i = 0;
                    for (; i < eleLen; i++) {
                        if (options.lazyload) {
                            picUrl = 'data-src'
                        }
                        hm += '<li>' + '<img ' + picUrl + '="' + 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)
                    });
                    if (options.ifMiddle) {
                        this.setImgMiddle()
                    }
                    this.setUlWidth()
                    this.imgLazyload(0)
                },
                imgLazyload: function(index) {
                    var ele = $('li', self).find('img').eq(index),
                        url = ele.attr('data-src')
                    if (url != undefined) {
                        ele.attr('src', url)
                        ele.removeAttr('data-src')
                    } else {
                        return false
                    }
                },
                cloneImg: function() {
                    var c1 = $('li', self).last().clone(),
                        c2 = $('li', self).first().clone();
                    $('ul', self).prepend(c1)
                    $('ul', self).append(c2)
                },
                setImgMiddle: function() {
                    var _this = this,
                        imgHeight, offsetHeight;
                    $('li', self).find('img').each(function(i) {
                        imgHeight = $(this).height()
                        offsetHeight = cHeight - imgHeight
                        if (offsetHeight != 0) {
                            $(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 slideEle = $(self).find('ul');
                    eleNum = this.getElementNum(); //设置ul宽度时,确认元素个数,并保存在闭包变量中
                    slideEle.width(cWidth * eleNum)
                    if (loop) {
                        loopIndex = 1;
                        slideEle.width(cWidth * (eleNum + 2))
                        slideEle.height(cHeight)
                        currentX = -cWidth * loopIndex
                        this.gotoAnimate('0ms', currentX)
                    }
                },
                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 lists = '',
                        i = 0;
                    for (; i < eleNum; 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(prefix + 'transition', prefix + 'transform 0ms ease-out')
                    utils.clearAutoplay()
                },
                touchMove: function(e) {
                    var slope = (startX - e.touches[0].pageX) / (startY - e.touches[0].pageY),
                        u = 2; //减速因素,越大减速越明显
                    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
                            if (!loop) { //如果不是循环滚动,边界设置减速
                                if (index <= 0 && offsetX > 0) {
                                    offsetX = offsetX / u
                                } else if (index >= eleNum - 1 && offsetX < 0) {
                                    offsetX = offsetX / u
                                }
                            }
                            slideEle.css(prefix + 'transform', 'translate3d(' + (currentX + offsetX) + 'px, 0,0)')
                            e.preventDefault()
                        }
                    }
                },
                touchEnd: function(e) {
                    // endX = e.changedTouches[0].pageX
                    // endY = e.changedTouches[0].pageY
                    if (defaultSwitch) {
                        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 _this = this,
                        tweentime = options.aniTime;
                    if (!loop) {
                        currentX = 0;
                        if (i > 0) {
                            index++
                            index = index >= eleNum ? eleNum - 1 : index
                        } else if (i < 0) {
                            index--
                            index = index <= 0 ? 0 : index
                        }
                        currentX = -(cWidth * index)
                        this.imgLazyload(index)
                        _this.gotoAnimate(tweentime + 'ms', currentX)
                    } else { //循环时
                        if (i > 0) {
                            index++
                            loopIndex++
                            index = index >= eleNum ? 0 : index
                            if (loopIndex >= eleNum + 1) {
                                loopIndex = 1
                                currentX = -(cWidth * loopIndex)
                                _this.gotoAnimate(tweentime + 'ms', -(cWidth * (eleNum + 1))) //先跳转至clone的图片
                                setTimeout(function() {
                                    _this.gotoAnimate('0ms', currentX) //时间到之后再变成正常的切换图片
                                }, tweentime)
                            } else {
                                currentX = -(cWidth * loopIndex)
                                _this.gotoAnimate(tweentime + 'ms', currentX)
                            }
                        } else if (i < 0) {
                            index--
                            loopIndex--
                            index = index < 0 ? eleNum - 1 : index
                            if (loopIndex < 1) {
                                loopIndex = eleNum
                                this.imgLazyload(0) //特殊情况处理,第0张图片的lazyload
                                currentX = -(cWidth * loopIndex)
                                _this.gotoAnimate(tweentime + 'ms', 0) //先跳转至clone的图片
                                setTimeout(function() {
                                    _this.gotoAnimate('0ms', currentX) //时间到之后再变成正常的切换图片
                                }, tweentime)
                            } else {
                                currentX = -(cWidth * loopIndex)
                                _this.gotoAnimate(tweentime + 'ms', currentX)
                            }
                        } else {
                            _this.gotoAnimate(tweentime + 'ms', currentX)
                        }
                        this.imgLazyload(loopIndex)
                    }
                    this.dotsOn(index)
                },
                gotoAnimate: function(sp, cx) {
                    var slideEle = $(self).find('ul');
                    slideEle.css(prefix + 'transition', prefix + 'transform ' + sp + ' ease-out')
                    slideEle.css(prefix + 'transform', 'translate3d(' + cx + 'px, 0,0)')
                }
            };
    
            var initialize = (function() { //初始化
                if (options.ifAjax) {
                    utils.render()
                }
                utils.imgResize()
                utils.bindEvents()
                if (options.dots) {
                    utils.dotsRender()
                }
                if (loop) {
                    utils.cloneImg()
                }
            })()
        }
    })(Zepto || jQuery)

    其实移动端的滑动组件编写起来与电脑上的还是有很大差异的,对于手指滑动的角度问题,动画需要使用css3,还有手指快速滑动图片切换的效果等等,这些都是电脑上不会遇到的问题。等以后有空了详细分析下怎么写滑动组件以及开发过程中会遇到的问题吧。

    demo下载

  • 相关阅读:
    docker常用命令
    docker安装注意事项
    DataGridView中实现自动编号
    Flask设置配置文件
    python路径找类并获取静态字段
    JavaScript数据类型
    php学习笔记6
    php学习笔记5
    php学习笔记4
    php学习笔记3
  • 原文地址:https://www.cnblogs.com/junhua/p/4464412.html
Copyright © 2020-2023  润新知