JavaScript實現無縫輪播圖: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0 ...
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|)