轮播的各种实现方式
作者:互联网
主要的业务逻辑
需求:
-
宽度自适应的走马灯,无限无缝轮播
-
无限的头像展示走马灯
轮播图需要宽度自适应,头像的轮播的宽度是固定的
基于需求的 轮播/走马灯 各种实现方案:
-
正常的js实现
实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style type="text/css"> * { margin: 0px; padding: 0px; list-style: none; } #div1 { width: 500px; height: 125px; margin: 60px auto 0px auto; border: 2px solid lightgreen; position: relative; overflow: hidden; } #ul_img { position: absolute; top: 0; left: 0; } #ul_img li { float: left; width: 125px; height: 125px; /*border: 1px solid red;*/ } #ul_img li img { width: 100%; height: 100%; } </style> </head> <body> <div id="div1"> <ul id="ul_img"> <li><img src="./upload/focus.jpg" alt="" /></li> <li><img src="./upload/focus1.jpg" alt="" /></li> <li><img src="./upload/focus2.jpg" alt="" /></li> <li><img src="./upload/focus3.jpg" alt="" /></li> </ul> </div> <script> var millisec = 10; //滚动间隔时间(毫秒) var intervalId; var left = 0; var ul; window.onload = function () { ul = document.getElementById('ul_img'); ul.innerHTML += ul.innerHTML; //复制一份相同的li var lis = ul.getElementsByTagName('li'); // 重新设置宽度,但是计算的方法是基于第一张图片的宽度*元素的个数 ul.style.width = lis[0].offsetWidth * lis.length + 'px'; intervalId = setInterval('scroll()', millisec); var div1 = document.getElementById('div1'); div1.onmouseover = function () { clearInterval(intervalId); }; div1.onmouseout = function () { intervalId = setInterval('scroll()', millisec); }; }; function scroll() { left -= 1; //定位小于等于总宽度的二分之一时,则left设置为0 if (left <= -ul.offsetWidth / 2) left = 0; ul.style.left = left + 'px'; } </script> </body> </html>
问题:只能在图片定宽的情况下实现
-
改版的js实现
方式:基于方式一的原理,获取所有图片的偏移量,动态计算ul的宽度
<script> window.onload = function () { let intervalTime = 5; let liMargin = 30; let liWidth = []; // 提前初始化用来装所有li的offsetWidth let left = 0; // 初始化left的值 let ul = document.getElementById('swiper_box').getElementsByTagName('ul')[0]; let li = ul.getElementsByTagName('li'); ul.innerHTML = ul.innerHTML + ul.innerHTML; // 将内容复制首中尾两分 li = [...ul.children]; // html类数组 转化 为数组 li.forEach(item => { // 获取所有li的宽度,并且加上右边框的宽度 liWidth.push(item.clientWidth + liMargin); }); let ulWidth = liWidth.reduce((tmp, item) => tmp + item); // 将所有的li的宽度累加 ul.style.width = ulWidth + liMargin + 'px'; // 根据计算出来的重新设置ul的高度,再加上收尾两边的边距 // 开启定时器调用调用滚动函数 let intervalID = setInterval(turnOnScroll, intervalTime); ul.onmouseover = function () { clearInterval(intervalID); }; ul.onmouseout = function () { intervalID = setInterval(turnOnScroll, intervalTime); }; console.log(ul.children.length); function turnOnScroll(params) { left = left - 1; if (left <= -ul.clientWidth / 2) left = `-${ul.children.length}`; ul.style.left = left + 'px'; } }; </script>
问题:有一点点偏移量的误差,实际效果会有一点卡顿的感觉
-
css3动画的实现
实现:基于动画的关键帧,控制定位的具体位置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> /* 视口大小 */ .wrapper { position: relative; height: 100px; width: 300px; overflow: hidden; } /* 实际的内容盒子 */ .wrapper__box-wrapper { height: 100px; width: 900px; position: absolute; left: 0px; background: #409eff; animation: move 5s linear infinite; } /* 上下行的容器 */ .wrapper__box-wrapper__line { /* 解决浮动导致的边距塌陷的问题 */ overflow: hidden; margin: 10px 0; } /* 上下行容器内的两份内容 */ /* 文字盒子的自适应: width: 50% + flex均分 */ .wrapper__box-wrapper__line div { float: left; display: flex; width: 50%; } .wrapper__box-wrapper__line span { text-align: center; background: rgba(255, 255, 255, 0.5); color: #fff; padding: 0 5px; margin-right: 10px; border-radius: 5px; flex: 1 0 auto; line-height: 35px; } @keyframes move { 0% { left: 0; } 100% { left: -450px; } } </style> </head> <body> <div class="wrapper"> <div class="wrapper__box-wrapper"> <div class="wrapper__box-wrapper__line"> <div> <span>什么是快乐星球</span> <span>爷青回</span> <span>躺平</span> <span>惊呆了</span> </div> <div> <span>什么是快乐星球</span> <span>爷青回</span> <span>躺平</span> <span>惊呆了</span> </div> </div> <div class="wrapper__box-wrapper__line"> <div> <span>requestAnimationFrame</span> <span>setTimeout</span> <span>setInterval</span> </div> <div> <span>requestAnimationFrame</span> <span>setTimeout</span> <span>setInterval</span> </div> </div> </div> </div> </body> </html>
问题:也是需要定宽,或者是知道图片列表的总宽度,才能基于关键帧进行定位
-
swiper组件的实现
很多细节无法自定义
因为宽度自适应,所以无法实现匀速的线性滚动
并且无法实现hover的放大效果
拖动后不能继续播放
.swiper-wrapper { height: 400px; width: 100vw; /* 改变swiper动画的实现曲线 */ -webkit-transition-timing-function: linear; /*之前是ease-out*/ -moz-transition-timing-function: linear; -ms-transition-timing-function: linear; -o-transition-timing-function: linear; transition-timing-function: linear; margin: 0 auto; } .swiper-wrapper .swiper-slide { height: 400px; width: auto; } .swiper-wrapper img { max-width: 100%; max-height: 100%; display: block; margin: auto; border-radius: 16px; height: 400px; object-fit: cover; }
<script> var swiper = new Swiper('.mySwiper', { loop: true, speed: 2500, // 缓动时长 //用户操作swiper之后,是否禁止autoplay.默认为true:停止。 // autoplayDisableOnInteraction: false, // grabCursor: true, // 显示拖动小手 // centeredSlides: true, // 设定为true时,当前的active slide 会居中,而不是默认状态下的居左。 // slidesOffsetBefore: 100, // 起始偏移量 spaceBetween: 20, slidesPerView: 'auto', freeMode: true, autoplay: { delay: 0, disableOnInteraction: false, //就算触摸了也继续滚动 stopOnLastSlide: false, }, }); </script>
补充:基于表格的实现形式:https://www.cnblogs.com/JiangXiaoTian/articles/2550540.html
标签:function,轮播,方式,width,实现,wrapper,li,ul,left 来源: https://www.cnblogs.com/ecat-octopus/p/16688086.html