纯js+css实现webApp轮播手滑成效
纯js+css实现webApp轮播手滑效果
网上发现的一个好的前端资源,给大家分享一下---纯js实现的淘宝首页轮播手滑前端特效。下面是我的源代码:用到的是freemarker框架
1.css样式代码
.addWrap { position: relative; width: 100%; background: #fff; margin: 0; padding: 0; margin-top: -4px; } .addWrap .swipe { overflow: hidden; visibility: hidden; position: relative; } .addWrap .swipe-wrap { overflow: hidden; position: relative; } .addWrap .swipe-wrap>div { float: left; width: 100%; position: relative; display: block; max-width: 100%; } #position { /* position: absolute; bottom: 0; right: 0; padding-right: 8px; margin: 0; background: #000; opacity: 0.4; width: 100%; filter: alpha(opacity = 50); text-align: center; */ display: none; } #position li { width: 10px; height: 10px; margin: 0 2px; display: inline-block; -webkit-border-radius: 5px; border-radius: 5px; background-color: #AFAFAF; } #position li.cur { background-color: #FF0000; } .img-responsive { display: block; max-width: 100%; height: auto; margin: 0 auto; }
2.html代码
<!-- 产品图片轮播手滑效果 begin --> <#if (product.imageUrl?size gt 0)> <div class="addWrap"> <div class="swipe" id="mySwipe"> <div class="swipe-wrap"> <#list product.imageUrl as url> <div> <img class="img-responsive" src="${url}" name="img-responsive" /></a> </div> </#list> </div> </div> <ul id="position"> <li class="cur"></li> <li class=""></li> <li class=""></li> <li class=""></li> <li class=""></li> </ul> </div> <#else> <div> <a href="javascript:;"><img class="img-responsive" src="${ctx}/static/images/default_product.png" name="img-responsive" /></a> </div> </#if> <!-- 产品图片轮播手滑效果 end-->
3.下面是js代码,js必须放在body最后。因为html document加载时有顺序的啦
<script src="${ctx}/static/js/swipe.js"></script> <script type="text/javascript"> //var bullets=document.getElementByName("img-responsive"); var postion = document.getElementById('position'); if (typeof (position) == "undefined") { } else { var bullets = document.getElementById('position') .getElementsByTagName('li'); var banner = Swipe(document.getElementById('mySwipe'), { auto : 2000, continuous : true, disableScroll : false, callback : function(pos) { var i = bullets.length; while (i--) { bullets[i].className = ' '; } bullets[pos].className = 'cur'; } }); } </script>
4.swipe.js代码
/* * Swipe 2.0 * * Brad Birdsall * Copyright 2013, MIT License * */ function Swipe(container, options) { "use strict"; // utilities var noop = function() {}; // 简单的无操作功能 var offloadFn = function(fn) { setTimeout(fn || noop, 0) }; // 卸载功能的执行 // 检查浏览器的功能 var browser = { addEventListener: !!window.addEventListener, touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch, transitions: (function(temp) { var props = ['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']; for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true; return false; })(document.createElement('swipe')) }; // 如果没有根元素退出 if (!container) return; var element = container.children[0]; var slides, slidePos, width; options = options || {}; var index = parseInt(options.startSlide, 10) || 0; var speed = options.speed || 300; options.continuous = options.continuous ? options.continuous : true; function setup() { // 缓存的幻灯片 slides = element.children; //创建一个数组来存储每个幻灯片的当前位置 slidePos = new Array(slides.length); // 确定每个幻灯片的宽度 width = container.getBoundingClientRect().width || container.offsetWidth; element.style.width = (slides.length * width) + 'px'; // 栈元素 var pos = slides.length; while(pos--) { var slide = slides[pos]; slide.style.width = width + 'px'; slide.setAttribute('data-index', pos); if (browser.transitions) { slide.style.left = (pos * -width) + 'px'; move(pos, index > pos ? -width : (index < pos ? width : 0), 0); } } if (!browser.transitions) element.style.left = (index * -width) + 'px'; container.style.visibility = 'visible'; } function prev() { if (index) slide(index-1); else if (options.continuous) slide(slides.length-1); } function next() { if (index < slides.length - 1) slide(index+1); else if (options.continuous) slide(0); } function slide(to, slideSpeed) { // 如果已经滑不要求 if (index == to) return; if (browser.transitions) { var diff = Math.abs(index-to) - 1; var direction = Math.abs(index-to) / (index-to); // 1:right -1:left while (diff--) move((to > index ? to : index) - diff - 1, width * direction, 0); move(index, width * direction, slideSpeed || speed); move(to, 0, slideSpeed || speed); } else { animate(index * -width, to * -width, slideSpeed || speed); } index = to; offloadFn(options.callback && options.callback(index, slides[index])); } function move(index, dist, speed) { translate(index, dist, speed); slidePos[index] = dist; } function translate(index, dist, speed) { var slide = slides[index]; var style = slide && slide.style; if (!style) return; style.webkitTransitionDuration = style.MozTransitionDuration = style.msTransitionDuration = style.OTransitionDuration = style.transitionDuration = speed + 'ms'; style.webkitTransform = 'translate(' + dist + 'px,0)' + 'translateZ(0)'; style.msTransform = style.MozTransform = style.OTransform = 'translateX(' + dist + 'px)'; } function animate(from, to, speed) { // 如果不是动画,只是重新定位 if (!speed) { element.style.left = to + 'px'; return; } var start = +new Date; var timer = setInterval(function() { var timeElap = +new Date - start; if (timeElap > speed) { element.style.left = to + 'px'; if (delay) begin(); options.transitionEnd && options.transitionEnd.call(event, index, slides[index]); clearInterval(timer); return; } element.style.left = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px'; }, 4); } // 安装程序自动幻灯片 var delay = options.auto || 0; var interval; function begin() { interval = setTimeout(next, delay); } function stop() { delay = 0; clearTimeout(interval); } // 设置初始变量 var start = {}; var delta = {}; var isScrolling; // 设置事件捕获 var events = { handleEvent: function(event) { switch (event.type) { case 'touchstart': this.start(event); break; case 'touchmove': this.move(event); break; case 'touchend': offloadFn(this.end(event)); break; case 'webkitTransitionEnd': case 'msTransitionEnd': case 'oTransitionEnd': case 'otransitionend': case 'transitionend': offloadFn(this.transitionEnd(event)); break; case 'resize': offloadFn(setup.call()); break; } if (options.stopPropagation) event.stopPropagation(); }, start: function(event) { var touches = event.touches[0]; // 测量的起始值 start = { // 得到初始的触摸坐标 x: touches.pageX, y: touches.pageY, // 存储时间确定接触时间 time: +new Date }; // 用于测试的第一移动事件 isScrolling = undefined; // 复位三角洲和最后计算值 delta = {}; // 设置touchmove和touchend监听 element.addEventListener('touchmove', this, false); element.addEventListener('touchend', this, false); }, move: function(event) { // 确保一个触摸不捏刷 if ( event.touches.length > 1 || event.scale && event.scale !== 1) return if (options.disableScroll) event.preventDefault(); var touches = event.touches[0]; // 计算改变后的 x 和 y delta = { x: touches.pageX - start.x, y: touches.pageY - start.y } // 确定测试运行——一个滚动时间测试 if ( typeof isScrolling == 'undefined') { isScrolling = !!( isScrolling || Math.abs(delta.x) < Math.abs(delta.y) ); } // 如果用户没有试图垂直滚动 if (!isScrolling) { // 防止本机滚动 event.preventDefault(); // 停止幻灯片显示 stop(); // 如果第一个或最后一个滑动阻力增加 delta.x = delta.x / ( (!index && delta.x > 0 // if first slide and sliding left || index == slides.length - 1 // or if last slide and sliding right && delta.x < 0 // and if sliding at all ) ? ( Math.abs(delta.x) / width + 1 ) // determine resistance level : 1 ); // no resistance if false // 转化 1:1 translate(index-1, delta.x + slidePos[index-1], 0); translate(index, delta.x + slidePos[index], 0); translate(index+1, delta.x + slidePos[index+1], 0); } }, end: function(event) { // 计算持续时间 var duration = +new Date - start.time; // 确定滑动尝试触发下一个/上一页滑动 var isValidSlide = Number(duration) < 250 // if slide duration is less than 250ms && Math.abs(delta.x) > 20 // and if slide amt is greater than 20px || Math.abs(delta.x) > width/2; // or if slide amt is greater than half the width // 如果尝试确定滑过去的开始和结束 var isPastBounds = !index && delta.x > 0 // 如果第一个幻灯片和幻灯片AMT大于0 || index == slides.length - 1 && delta.x < 0; // 或者如果最后一张幻灯片,幻灯片amt小于0 // 确定滑动方向(true:right, false:left) var direction = delta.x < 0; // 如果不垂直滚动 if (!isScrolling) { if (isValidSlide && !isPastBounds) { if (direction) { move(index-1, -width, 0); move(index, slidePos[index]-width, speed); move(index+1, slidePos[index+1]-width, speed); index += 1; } else { move(index+1, width, 0); move(index, slidePos[index]+width, speed); move(index-1, slidePos[index-1]+width, speed); index += -1; } options.callback && options.callback(index, slides[index]); } else { move(index-1, -width, speed); move(index, 0, speed); move(index+1, width, speed); } } // 取消touchmove和touchend事件监听器,直到touchstart再次调用 element.removeEventListener('touchmove', events, false) element.removeEventListener('touchend', events, false) }, transitionEnd: function(event) { if (parseInt(event.target.getAttribute('data-index'), 10) == index) { if (delay) begin(); options.transitionEnd && options.transitionEnd.call(event, index, slides[index]); } } } // 触发设置 setup(); // 如果适用则开始自动幻灯片 if (delay) begin(); // 添加事件监听器 if (browser.addEventListener) { // 设置touchstart事件元素 if (browser.touch) element.addEventListener('touchstart', events, false); if (browser.transitions) { element.addEventListener('webkitTransitionEnd', events, false); element.addEventListener('msTransitionEnd', events, false); element.addEventListener('oTransitionEnd', events, false); element.addEventListener('otransitionend', events, false); element.addEventListener('transitionend', events, false); } //设置在窗口调整大小事件 window.addEventListener('resize', events, false); } else { window.onresize = function () { setup() }; // to play nice with old IE } // 公开Swipe API return { setup: function() { setup(); }, slide: function(to, speed) { slide(to, speed); }, prev: function() { // cancel slideshow stop(); prev(); }, next: function() { stop(); next(); }, getPos: function() { // return current index position return index; }, kill: function() { // 取消幻灯片 stop(); // reset element element.style.width = 'auto'; element.style.left = 0; // reset slides var pos = slides.length; while(pos--) { var slide = slides[pos]; slide.style.width = '100%'; slide.style.left = 0; if (browser.transitions) translate(pos, 0, 0); } // 删除事件侦听器 if (browser.addEventListener) { // remove current event listeners element.removeEventListener('touchstart', events, false); element.removeEventListener('webkitTransitionEnd', events, false); element.removeEventListener('msTransitionEnd', events, false); element.removeEventListener('oTransitionEnd', events, false); element.removeEventListener('otransitionend', events, false); element.removeEventListener('transitionend', events, false); window.removeEventListener('resize', events, false); } else { window.onresize = null; } } } } if ( window.jQuery || window.Zepto ) { (function($) { $.fn.Swipe = function(params) { return this.each(function() { $(this).data('Swipe', new Swipe($(this)[0], params)); }); } })( window.jQuery || window.Zepto ) }