其他分享
首页 > 其他分享> > 轮播的各种实现方式

轮播的各种实现方式

作者:互联网

主要的业务逻辑

需求:

  1. 宽度自适应的走马灯,无限无缝轮播

    image

  2. 无限的头像展示走马灯

image

轮播图需要宽度自适应,头像的轮播的宽度是固定的

基于需求的 轮播/走马灯 各种实现方案:

  1. 正常的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>
    
    

    问题:只能在图片定宽的情况下实现

image

  1. 改版的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>
    

    问题:有一点点偏移量的误差,实际效果会有一点卡顿的感觉

  2. 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>
    
    

    问题:也是需要定宽,或者是知道图片列表的总宽度,才能基于关键帧进行定位

  3. 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