簡體   English   中英

vanilla javascript 和 css 圖像滑塊無法正常工作

[英]vanilla javascript & css image slider not working properly

我使用一些 javascript 和 css 創建了一個包含許多圖像的圖像滑塊。 我只是使用客戶端寬度來獲取圖像的大小(略有不同)並使用計數器變量計算 translateX 距離。 最后添加了 css 過渡。 但是我似乎無法讓滑塊正確翻譯整個圖像。 我不知道為什么會出錯。 我在計算響應性時使用了“vw”。 我是 javascript 的新手,也希望了解有關代碼其他部分的其他部分的任何提示。

這是 JS 小提琴鏈接 - https://jsfiddle.net/n6smpv2j/15/

HTML

<div id="lookbook" data-tab-content class="black-text">
            <div class="lookbook-nav">
               <button id="left">←</button>
               <button id="right">→</button>
            </div>
            <div class="lookbook">
               <div class="slider">
                  <img src="https://loremflickr.com/640/360" id="lastClone" alt="">
                  <img src="https://picsum.photos/640/400">
                  <img src="https://loremflickr.com/640/360">
                  <img src="https://picsum.photos/640/400">
                  <img src="https://loremflickr.com/640/360">
                  <img src="https://picsum.photos/640/400">
                  <img src="https://loremflickr.com/640/360">
                  <img src="https://picsum.photos/600/400">
                  <img src="https://fillmurray.com/600/330">
                  <img src="https://picsum.photos/600/400">
                  <img src="https://fillmurray.com/600/330">
                  <img src="https://picsum.photos/600/400">
                  <img src="https://loremflickr.com/640/360">
                  <img src="https://picsum.photos/600/400">
                  <img src="https://loremflickr.com/640/360">
                  <img src="https://picsum.photos/600/400" id="firstClone" alt="">
               </div>
            </div>
         </div>

JS

const slider = document.querySelector('.slider');
const sliderImages = document.querySelectorAll('.slider img');
const leftbtn = document.querySelector('#left');
const rightbtn = document.querySelector('#right');
let counter = 1;
const size = sliderImages[0].clientWidth;
slider.style.transform = 'translateX(' + (-size * counter) + 'vw)';

rightbtn.addEventListener('click', () => {
   if (counter >= sliderImages.length - 1) return;
   slider.style.transition = "transform 0.4s ease-in";
   counter++;
   slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
})

leftbtn.addEventListener('click', () => {
   if (counter <= 0) return;
   slider.style.transition = "transform 0.4s ease-in";
   counter--;
   slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
})

slider.addEventListener('transitionend', () => {
   if (sliderImages[counter].id === "lastClone") {
      slider.style.transition = "none";
      counter = sliderImages.length - 2;
      slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
   }
   if (sliderImages[counter].id === "firstClone") {
      slider.style.transition = "none";
      counter = sliderImages.length - counter;
      slider.style.transform = 'translateX(' + (-size * counter) + 'vw)'
   }
})

CSS

#lookbook {
   width: 100vw;
   height: 100vh;
}

.lookbook-nav {
   width: 70vw;
   height: 10vh;
   margin-left: 15vw;
   margin-top: 45vh;
   position: absolute;
   display: flex;
   justify-content: space-between;
   align-items: center;
}

button {
   border: none;
   outline: none;
   background: transparent;
   font-size: 2rem;
   /* font-weight: bold; */
   cursor: pointer;
}

.lookbook-nav button {
   border: none;
   outline: none;
   background: transparent;
   font-size: 2rem;
   /* font-weight: bold; */
   cursor: pointer;
}

button:hover {
   opacity: 0.4;
}

.lookbook {
   width: 56vw;
   height: 91vh;
   margin: auto;
   overflow: hidden;
}

.lookbook img {
   width: 100%;
   height: auto !important;
}

.slider {
   margin-top: 10vh;
   display: flex;
   width: auto;
   
}

這是因為size是以像素為單位計算的,正如您在此處看到的。 因此,要獲得vw的寬度,您可以使用以下函數作為

const size = vw(sliderImages[0].clientWidth);

function vw(v) {
    var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    return (v * w) / 100;
}

@DecjazMach 的答案解決了最重要的問題,但並未涵蓋所有問題。 例如,該解決方案也仍然使用第一張圖像的寬度來設置可見滑塊的寬度。 這在很多情況下都沒有問題,但是如果第一張圖像是瘦高的肖像而其余的風景,反之亦然呢?

@Laiqa Mohid 也歡迎任何其他建議,所以這里有一些試圖簡化事情的建議,例如最小化 JS 中所需的計算和系統必須在點擊時完成的“工作”。 你可以在這里嘗試http://bayeuxtapestry.rgspaces.org.uk/slider

筆記:

滑塊可見部分的大小不依賴於第一張圖像的尺寸

imgs 已被 divs + background-image 替換,以便可以適應不同的大小/縱橫比而無需任何 javascript 計算 - 這會自動幫助響應

這些 div 的尺寸都相同,因此滑塊需要移動的量不取決於圖像的大小

未填滿整個寬度的圖像(因為它們相對太高)將居中

圖像也垂直居中。 如果需要,可以通過更改 .slider div 中的背景位置來更改(例如對齊滑塊的頂部)

使用 transform:translateX 可以工作,但需要在 Javascript 中進行計算。 我們可以改用 CSS 動畫,只需要移動當前可見的幻燈片和接下來要顯示的幻燈片。

圖像服務有時不提供圖像,所以我使用了我自己的 - 故意使用不同的尺寸和縱橫比(包括縱向)

使用這種方法可以有一個連續的滑塊 - 如果用戶點擊最后一張幻燈片,則顯示第一張幻燈片。

這是代碼:

<!DOCTYPE html>
<html>
<head>
<title>Slider</title>
<meta charset="utf-8">
<style>
#lookbook {
  width: 100vw;
  height: 100vh;
  margin:0;
  padding:0;
  overflow:hidden;
}

.lookbook-nav {
  width: 70vw;
  height: 10vh;
  margin-left: 15vw;
  margin-top: 45vh;
  position: absolute;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

button {
  border: none;
  outline: none;
  background: transparent;
  font-size: 2rem;
  /* font-weight: bold; */
  cursor: pointer;
}

.lookbook-nav button {
  border: none;
  outline: none;
  background: transparent;
  font-size: 2rem;
  /* font-weight: bold; */
  cursor: pointer;
}

button:hover {
  opacity: 0.4;
}

div .lookbook {
  width: 56vw;
}

.lookbook {
  height: 91vh;
  margin: auto;
  overflow: hidden;
}

div.slider{
  margin:0;
  margin-top: 10vh;
  height:81vh;/* this is height of (lookbook - margin-top) - probably better done through flex */
  position:relative;
  top:0;
  padding:0;
  width:100%;
}

@keyframes slideouttoleft {
  from {
   left: 0;
   visibility:visible;
  }
  to {
   left: -100%;
   visibility:hidden;
  }
}
@keyframes slideinfromright {
  from {
   left: 100%;
   visibility:visible;
  }
  to {
   left: 0;
   visibility:visible;
  }
}
@keyframes slideouttoright {
  from {
   left: 0;
   visibility:visible;
  }
  to {
   left: 100%;
   visibility:hidden;
  }
}
@keyframes slideinfromleft {
  from {
   left: -100%;
   visibility:visible;
  }
  to {
   left: 0;
   visibility:visible;
  }
}

.slider div {
  position:absolute;
  top:0;
  left:0;
  overflow:hidden;
  visibility:hidden;
  margin: 0;
  padding: 0;
  width:100%;
  height:100%;
  background-size: contain;
  background-position: center center;
  background-repeat: no-repeat no-repeat;
  animation-duration: 0.4s;
  animation-delay: 0s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-timing-function: ease-in;
  animation-fill-mode: forwards;
}
</style>
</head>
<body>

<div id="lookbook" data-tab-content class="black-text">
        <div class="lookbook-nav">
          <button id="left">←</button>
          <button id="right">→</button>
        </div>
        <div class="lookbook">
          <div class="slider">
          <!-- images taken from Reading (UK) Museum's Victorian copy of the Bayeux Tapestry -->
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/boat-and-horses-768x546.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/two-horses-300x212.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/woman-and-child-1200x901.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/archer-2-768x1100.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/boat-builder-2-878x1024.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/group-1-768x603.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/pointing-horseman-768x853.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/group-2-768x619.png);"></div>
            <div style="background-image:url(https://rgspaces.org.uk/bayeuxtapestry/wp-content/uploads/carrying-casket-768x556.png);"></div>
          </div>
        </div>
</div>
<script>
const slider = document.querySelector('.slider');
const sliderImages = document.querySelectorAll('.slider div');
const leftbtn = document.querySelector('#left');
const rightbtn = document.querySelector('#right');
const numImgs=sliderImages.length;
let curImg = 0;

rightbtn.addEventListener('click', () => {
  sliderImages[curImg].style.animationName='slideouttoleft';
  curImg=(curImg+1)%numImgs;
  sliderImages[curImg].style.animationName='slideinfromright';
})

leftbtn.addEventListener('click', () => {
  sliderImages[curImg].style.animationName='slideouttoright';
  curImg=curImg==0? numImgs-1 : Math.abs((curImg-1)%numImgs);
  sliderImages[curImg].style.animationName='slideinfromleft';
})

function initialize() {
  sliderImages[0].style.animationName='slideinfromright';
}

window.onload=initialize;

</script>
</body>
</html>

出於某種原因,從該源加載的圖像不起作用,所以我將它們下載到本地,它們確實起作用了,我也對您的 CSS 進行了一些修改。

 var slider = document.getElementById("slider"); var slides = slider.childElementCount; var i = 0; document.getElementById("right").addEventListener("click", function () { i == slides - 1 ? (i = 0) : i++; slider.style.transform = "translate(-" + 600 * i + "px)"; });
 body { background-color: aqua; } #lookbook { position: relative; box-sizing: content-box; height: auto; max-width: 600px; margin: auto; } .lookbook-nav { position: absolute; display: flex; justify-content: space-between; width: 100%; height: 100%; } button { border: none; outline: none; background: transparent; font-size: 2rem; cursor: pointer; } .lookbook-nav button { border: none; outline: none; background: transparent; font-size: 2rem; /* font-weight: bold; */ cursor: pointer; color: beige; z-index: 2; } button:hover { opacity: 0.4; } .lookbook { width: auto; height: 91vh; margin: auto; overflow: hidden; } .lookbook img { width: 600px; height: auto !important; } .slider { margin-top: 10vh; display: flex; /* align-items: flex-end; */ width: auto; /* height: 700px; */ transition: 0.5s ease-in-out; }
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Slider</title> </head> <body> <div id="lookbook" data-tab-content class="black-text"> <div class="lookbook-nav"> <button id="left">←</button> <button id="right">→</button> </div> <div class="lookbook"> <div class="slider" id="slider"> <img src="https://picsum.photos/600/360" alt="" /> <img src="https://picsum.photos/600/360" alt="" /> <img src="https://picsum.photos/600/360" alt="" /> <img src="https://picsum.photos/600/360" alt="" /> <img src="https://picsum.photos/600/360" alt="" /> <img src="https://picsum.photos/600/360" alt="" /> </div> </div> </div> </body> </html>

我只是讓一個導航箭頭工作,但應該以相反的順序做同樣的事情,你也不必擔心計數器,因為它會檢測你在滑塊內有多少圖像。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM