一直都没有封装过一套移动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: 要想写能用的滑动组件,千万别看慕课网的那个教程啊!!!
时间: 2024-10-17 15:08:44