[英]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.