21.JavaScript实现无缝轮播图
JavaScript实现无缝轮播图:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .container { position: relative; width: 500px; height: 400px; border: 1px solid #fff; margin: 20px auto; overflow: hidden; cursor: pointer; } .container .images img { display: block; float: left; } .container .dots { position: absolute; margin: 0 auto; left: 0; right: 0; bottom: 10px; background: rgba(255, 255, 255, .3); padding: 5px; border-radius: 20px; } .container .dots span { margin: 2px; width: 8px; height: 8px; display: block; border-radius: 50%; background: rgba(255, 255, 255, .5); float: left; } .container .dots span.active { background: #f40; } .container .arrow { display: none; } .container:hover .arrow { display: block; } .container .arrow .item { width: 40px; height: 40px; background: rgba(255, 255, 255, .5); color: #fff; position: absolute; top: 0; bottom: 0; margin: auto 0; text-align: center; line-height: 40px; font-size: 20px; } .container .arrow .leftArrow { left: 0; border-radius: 0 20px 20px 0; } .container .arrow .rightArrow { right: 0; border-radius: 20px 0 0 20px; } </style> </head> <body> <div class="container"> <div class="images"> </div> <div class="dots"> </div> <div class="arrow"> <div class="item leftArrow"><</div> <div class="item rightArrow">></div> </div> </div> <script> var config = { imgWidth: 500, //图片宽度 dotWidth: 12, //小圆点宽度 imageArray: ["./image/5.jpg", "./image/1.jpg", "./image/2.jpg", "./image/3.jpg", "./image/4.jpg", "./image/5.jpg", "./image/1.jpg" ], //存储图片路径的数组 doms: { images: document.querySelector(".images"), //存放图片的dom dots: document.querySelector(".dots"), //圆点的dom leftArrow: document.querySelector(".item.leftArrow"), //左一张的dom rightArrow: document.querySelector(".item.rightArrow") //右一张的dom }, currentIndex: 2, //当前展示的图片下标 timer: { //计时器配置 id: null, //计时器id duration: 16, //每次切换图片,运动的间隔时间 totalTime: 1000 //每次切换图片,运动的时间总长 } }; initImages(); initDots(); //初始化图片元素 function initImages() { //创建图片元素 config.doms.images.style.width = config.imageArray.length * config.imgWidth + "px"; for (var i = 0; i < config.imageArray.length; i++) { var img = document.createElement("img"); img.src = config.imageArray[i]; config.doms.images.appendChild(img); } //展示第一张图片1.jpg config.doms.images.style.marginLeft = -config.imgWidth * config.currentIndex + "px"; } //创建圆点元素 function initDots() { config.doms.dots.style.width = (config.imageArray.length - 2) * config.dotWidth + "px"; for (var i = 0; i < config.imageArray.length - 2; i++) { var dot = document.createElement("span"); config.doms.dots.appendChild(dot); } config.doms.dots.children[config.currentIndex - 1].className = "active"; } //点击左箭头、右箭头、和圆点 config.doms.leftArrow.onclick = config.doms.rightArrow.onclick = config.doms.dots.onclick = function (e) { if (e.target.tagName === "DIV" && e.target.classList.contains("leftArrow")) { //点击左箭头 var index = config.currentIndex - 1;//向左跳转图片的下标 if(index === 0){// index = 5; } jumpToImage(index, "left"); } else if (e.target.tagName === "DIV" && e.target.classList.contains("rightArrow")) { //点击右箭头 var index = config.currentIndex + 1;//向右跳转图片的下标 if(index === 6){// index = 1; } jumpToImage(index, "right"); } else if (e.target.tagName === "SPAN" && e.target.parentElement && e.target.parentElement.classList .contains("dots")) { //点击小圆点 var index = Array.from(config.doms.dots.children).indexOf(e.target) + 1; jumpToImage(index, (index > config.currentIndex) ? "right" : "left"); } } //跳转到哪张图片 function jumpToImage(index, direction) { //index:下一张图片的下标(1,25);direction方向(1.left:左;2.right:右); if (index === config.currentIndex) { //若要跳转的图片下标和当前下标一样,不执行 return; } if (!direction) { //方向默认:为右 direction = "right"; } //要运动到的目标marginLeft var newMarginLeft = -index * config.imgWidth; //图片切换 //config.doms.images.style.marginLeft = newMarginLeft + "px"; autoPlay(); //圆点也自动切换 for (var i = 0; i < config.doms.dots.children.length; i++) { config.doms.dots.children[i].classList.remove("active"); } config.doms.dots.children[index - 1].className = "active"; //切换完成后,改变当前图片下标 config.currentIndex = index; //图片渐变动画,一点一点的改变marginLeft function autoPlay() { stopPlay(); //在播放轮播图之前,把上次的动画先停掉 //当前的marginLeft var currentMarginLeft = parseFloat(window.getComputedStyle(config.doms.images).marginLeft); //图片总长度,不能算第一张和最后一张,这两张是额外增加重复的两张 var allImagesLength = (config.imageArray.length - 2) * config.imgWidth; //1.计算运动总次数 var frequency = Math.ceil(config.timer.totalTime / config.timer.duration); var currentNum = 0; //当前运动的次数 //2.计算运动的总距离 var allDistance = 0; if (direction == "left") { //向左运动 if (newMarginLeft > currentMarginLeft) { //目标marginLeft > 当前marginLeft //总距离 = 目标marginLeft - 当前marginLeft allDistance = newMarginLeft - currentMarginLeft; } else { //总距离 = 图片总长度 - |目标marginLeft - 当前marginLeft| allDistance = allImagesLength - Math.abs(newMarginLeft - currentMarginLeft); } } else { //向右运动 if (newMarginLeft < currentMarginLeft) { //目标marginLeft < 当前marginLeft //总距离 = 目标marginLeft - 当前marginLeft allDistance = newMarginLeft - currentMarginLeft; } else { //目标marginLeft > 当前marginLeft //总距离 = -(图片总长度 - |目标marginLeft - 当前marginLeft|) allDistance = -(allImagesLength - Math.abs(newMarginLeft - currentMarginLeft)); } } //3.计算每次运动改变的距离 var everyDistance = allDistance / frequency; //每次运动距离 = 运动总距离 / 运动总次数 config.timer.id = setInterval(function () { //改变图片的marginLeft currentMarginLeft += everyDistance; //若图片向右移动到额外的第一张(即数组中最后一张图片) if (direction === "right" && Math.floor(Math.abs(currentMarginLeft)) > allImagesLength) { currentMarginLeft += allImagesLength; //图片瞬间挪回第一张图片对应的位置 } else if (direction === "left" && Math.ceil(Math.abs(currentMarginLeft)) < config .imgWidth) { //若图片向左移动到额外的最后一张(即数组中第一张图片) currentMarginLeft -= allImagesLength; //图片瞬间挪回最后一张图片对应的位置 } config.doms.images.style.marginLeft = currentMarginLeft + "px"; currentNum++; //每执行一次,当前运动次数++ if (currentNum === frequency) { //达到运动总次数,停止运动 stopPlay(); } }, config.timer.duration); } //停止播放 function stopPlay() { clearInterval(config.timer.id); config.timer.id = null; } } </script> </body> </html>
index.html
效果展示:
最后一张图片切换第一张图片的效果
图片数组存储一共七张图片,但是1.jpg 和 5.jpg存放了两次,用来衔接。这样从5.jpg切换到1.jpg的时候不会出现断档,五张图片的宽高是500 X 200
制作无缝轮播图的难点:
计算运动的总距离
向左运动,目标margin-left 和 当前的margin-left
目标marginLeft > 当前marginLeft //总距离 = 目标marginLeft - 当前marginLeft
目标marginLeft < 当前marginLeft //总距离 = 图片总长度 - |目标marginLeft - 当前marginLeft|
向右运动,目标margin-left 和 当前的margin-left
目标marginLeft < 当前marginLeft //总距离 = 目标marginLeft - 当前marginLeft
目标marginLeft > 当前marginLeft //总距离 = -(图片总长度 - |目标marginLeft - 当前marginLeft|)
赞 (0)