移动端轮播图
原生JS实现移动端轮播图结构搭建html代码&css代码 实现思路JS核心代码原生JS实现移动端轮播图
结构搭建
html代码&css代码
<style>* {margin: 0;padding: 0;}ul li {list-style-type: none;}a {text-decoration: none;}.banner-wrap {width: 100vw;background-color: #bfa;}.banner-wrap .banner {width: 80%;margin: 0 auto;overflow: hidden;position: relative;}/* 设置ul */.slider-wrap {width: 500%;/* 设置应该显示的第一张图片,而非复制的放在最前边的最后一张图 */margin-left: -100%;}.slider-wrap li {width: 20%;height: 20vh;float: left;}.slider-wrap img {width: 100%;}/* 设置小圆圈 */.pointer {position: absolute;bottom: 15px;right: 15px;}.pointer li {width: 8px;height: 8px;border-radius: 4px;list-style-type: none;display: inline-block;background-color: hsla(0, 0%, 100%, .4);}.pointer li.current {width: 18px;}</style></head><body><div class="banner-wrap"><!-- 创建banner区域 --><div class="banner"><a href=""><span>特价直播</span><span>特价好货直播中</span></a><!-- 轮播图容器 --><ul class="slider-wrap"><li class="slider"><a href=""><img src="../../images/p-banner3.jpg" alt=""></a></li><li class="slider"><a href=""><img src="../../images/p-banner1.jpg" alt=""></a></li><li class="slider"><a href=""><img src="../../images/p-banner2.jpg" alt=""></a></li><li class="slider"><a href=""><img src="../../images/p-banner3.jpg" alt=""></a></li><li class="slider"><a href=""><img src="../../images/p-banner1.jpg" alt=""></a></li></ul><!-- 小圆圈 --><ol class="pointer"><li class="current"></li><li></li><li></li></ol></div></div>
实现思路
图片滚动:移动端没有兼容性问题,此时可以不必使用之前的动画函数,才用定时器
和css动画中的transform:translate
及transition
结合实现滚动动画
效果无缝滚动:同理PC端需要将第一张添加到最后一张后,需要将最后一张添加到第一张前;pc端为鼠标点击事件,移动端为触摸点拖动小圆圈跟随变化:单独设置current样式,用classList切换类current
(PC端时才用的排他写法);图片过渡之后小圆圈再变化,用到transitionend
事件手指滑动轮播图:本质是ul跟随手指移动,简单说就是移动端的拖动元素功能; 利用触摸事件touchstart来获取手指初始坐标; touchmove来计算手指的滑动距离,并且移动盒子; touchend手指离开事件通过滑动的距离判断不同的情况: 如果移动距离小于某个像素,就回弹到原来的位置,如果移动距离大于某个像素就滑动到上一张或者下一张性能优化1:当我们点击轮播图的图片时,又不想移动了,这时候手指离开需要执行一大段代码。优化办法为:加一个flag全局变量,只有当手指真的移动了,才执行手指离开的一系列代码操作性能优化2:如果屏幕比较长,手指在移动轮播图的过程可能会滚动屏幕。优化方法为:取消默认滚动屏幕的行为。在touchmove事件里加上e.preventDefault();即可classList属性的用法:
JS核心代码
<script>// 获取元素var ul = document.querySelector('.slider-wrap');var lis = ul.querySelectorAll('li');var banner = document.querySelector('.banner');var ol = banner.lastElementChild;// 1.图片滚动// 获取banner宽度var w = banner.offsetWidth;var index = 0;var timer = setInterval(function () {index++;var translatex = -index * w;// ul.style.transform = 'translateX('+ translatex + ' px)';//这个就不行?ul.style.transition = 'all .3s';ul.style.transform = 'translateX(' + translatex + 'px)';}, 2000);// 2.无缝滚动// 等图片过渡完成之后,再去判断监听过渡完成的事件ul.addEventListener('transitionend', function () {console.log(1);if (index >= 3) {index = 0;// 去掉过渡,让ul快速跳到目标位置ul.style.transition = 'none';//利用最新的索引号乘以宽度 继续滚动图片var translatex = -index * w;ul.style.transform = 'translateX(' + translatex + 'px)';} else if (index < 0) {index = 2;ul.style.transition = 'none';//利用最新的索引号乘以宽度 继续滚动图片var translatex = -index * w;ul.style.transform = 'translateX(' + translatex + 'px)';}// 3.小圆点跟随变化ol.querySelector('.current').classList.remove('current');ol.children[index].classList.add('current');})// 4. 手指滑动轮播图// 触摸元素touchstart:获取手指初始坐标var startX = 0;var moveX = 0; // 后面会使用这个移动距离,所以要定义为全局变量var flag = false; //用来标志手指是否真的移动,还是只是点击ul.addEventListener('touchstart', function (e) {startX = e.targetTouches[0].pageX;// 手指触摸的时候就停止定时器clearInterval(timer);});// 移动手指touchmove:计算手指的滑动距离,并且移动盒子ul.addEventListener('touchmove', function (e) {// 计算移动距离// e.targetTouches[0]为第一个手指,[1]表示第二个手指moveX = e.targetTouches[0].pageX - startX;// 移动盒子:盒子原来的位置 + 手指移动的距离var translateX = -index * w + moveX;// 手指拖动的时候,不需要动画效果,所以要取消过渡效果ul.style.transition = 'none';ul.style.transform = 'translateX(' + translateX + 'px)';flag = true;e.preventDefault(); //组织滚动屏幕的行为});// 手指离开,根据移动距离去判断是回弹还是播放上一张或者下一张ul.addEventListener('touchend', function (e) {// 只有手指移动过了,才执行下面的代码if (flag) {//(1)如果移动距离大于50像素,则播放上一张或者下一张if (Math.abs(moveX) > 50) {// 如果是右滑就是播放上一张,moveX是正值if (moveX > 0) {index--;} else {// 如果是左滑就是播放下一张,moveX是负值index++;}// 用最新的index乘以宽度var translateX = -index * w;ul.style.transition = 'all .3s';ul.style.transform = 'translateX(' + translateX + 'px)';} else {//(2)如果移动距离小于50像素就回弹var translateX = -index * w;ul.style.transition = 'all .1s';ul.style.transform = 'translateX(' + translateX + 'px)';}}// 手指离开的时候就重新开启定时器// 注意:开启定时器之前要先清空之前的定时器,保证当前只有一个定时器在执行clearInterval(timer);timer = setInterval(function () {index++;var translateX = -index * w;// 添加动画效果ul.style.transition = 'all .3s';ul.style.transform = 'translateX(' + translateX + 'px)';}, 2000);});</script>