Como criar um carrossel vertical usando JavaScript e CSS simples
A Minha HTML:
<div class="slider vertical" >
<img class="first opened" src="http://malsup.github.io/images/beach1.jpg">
<img class="opened" src="http://malsup.github.io/images/beach2.jpg">
<img src="http://malsup.github.io/images/beach3.jpg">
<img src="http://malsup.github.io/images/beach4.jpg">
<img src="http://malsup.github.io/images/beach5.jpg">
<img src="http://malsup.github.io/images/beach9.jpg">
</div>
<div class="center">
<button id="prev">∧ Prev</button>
<button id="next">∨ Next</button>
</div>
JavaScript:
var next = document.getElementById('next');
var target = document.querySelector('.first');
next.addEventListener('click', nextImg, false);
function nextImg(){
if (target.classList.contains('opened')) {
target.classList.remove('opened');
target.classList.add('closed');
} else {
target.classList.remove('closed');
target.classList.add('opened');
}
}
CSS:
div.vertical {
width: 100px;
}
.slider {
position: relative;
overflow: hidden;
height: 250px;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
box-sizing:border-box;
-webkit-transition:-webkit-transform 1.3s ease;
-moz-transition: -moz-transform 1.3s ease;
-ms-transition: -ms-transform 1.3s ease;
transition: transform 1.3s ease;
}
.slider img {
width: 100px;
height: auto;
padding: 2px;
}
.first.closed{
/* partially offscreen */
-webkit-transform: translate(0, -80%);
-moz-transform: translate(0, -80%);
-ms-transform: translate(0, -80%);
transform: translate(0, -80%);
}
.first.opened{
/* visible */
-webkit-transform: translate(0, 0%);
-moz-transform: translate(0, 0%);
-ms-transform: translate(0, 0%);
transform: translate(0, 0%);
}
O meu modo de pensar foi:
- usar as classes para mover e mostrar o conteúdo
- usar JavaScript para adicionar e remover classes
1 answers
Uma alternativa à utilização das propriedades CSS transform
é dar ao carrossel um posicionamento absoluto dentro de uma embalagem div
e manipular a propriedade do carrossel top
. Então você pode usar qualquer função de suavização que você gosta para animar o movimento de deslizamento. No excerto abaixo, eu uso cúbico de entrada / saída .
Uma coisa complicada a ter em atenção é a ordem pela qual você roda as imagens e executa a animação deslizante. Quando você quer mostrar a próxima imagem abaixo, você tem to:
- desliza o carrossel pela altura de uma moldura
- roda a primeira imagem até ao fim
- repõe a posição vertical do carrossel a zero
Para mostrar a imagem seguinte acima:
- roda a última imagem para o início
- mova instantaneamente o carrossel pela altura de uma moldura
- deslize o carrossel para baixo até que a sua posição vertical atinja zero
No seguinte trecho, você pode definir a largura do carrossel ajustando Carousel.width
no topo do script. (Embora a altura da imagem não tenha que ser a mesma que a largura da imagem, eu assumo que todas as imagens têm as mesmas dimensões.) Você também pode brincar com os parâmetros Carousel.numVisible
e Carousel.duration
.
var Carousel = {
width: 100, // Images are forced into a width of this many pixels.
numVisible: 2, // The number of images visible at once.
duration: 600, // Animation duration in milliseconds.
padding: 2 // Vertical padding around each image, in pixels.
};
function rotateForward() {
var carousel = Carousel.carousel,
children = carousel.children,
firstChild = children[0],
lastChild = children[children.length - 1];
carousel.insertBefore(lastChild, firstChild);
}
function rotateBackward() {
var carousel = Carousel.carousel,
children = carousel.children,
firstChild = children[0],
lastChild = children[children.length - 1];
carousel.insertBefore(firstChild, lastChild.nextSibling);
}
function animate(begin, end, finalTask) {
var wrapper = Carousel.wrapper,
carousel = Carousel.carousel,
change = end - begin,
duration = Carousel.duration,
startTime = Date.now();
carousel.style.top = begin + 'px';
var animateInterval = window.setInterval(function () {
var t = Date.now() - startTime;
if (t >= duration) {
window.clearInterval(animateInterval);
finalTask();
return;
}
t /= (duration / 2);
var top = begin + (t < 1 ? change / 2 * Math.pow(t, 3) :
change / 2 * (Math.pow(t - 2, 3) + 2));
carousel.style.top = top + 'px';
}, 1000 / 60);
}
window.onload = function () {
document.getElementById('spinner').style.display = 'none';
var carousel = Carousel.carousel = document.getElementById('carousel'),
images = carousel.getElementsByTagName('img'),
numImages = images.length,
imageWidth = Carousel.width,
aspectRatio = images[0].width / images[0].height,
imageHeight = imageWidth / aspectRatio,
padding = Carousel.padding,
rowHeight = Carousel.rowHeight = imageHeight + 2 * padding;
carousel.style.width = imageWidth + 'px';
for (var i = 0; i < numImages; ++i) {
var image = images[i],
frame = document.createElement('div');
frame.className = 'pictureFrame';
var aspectRatio = image.offsetWidth / image.offsetHeight;
image.style.width = frame.style.width = imageWidth + 'px';
image.style.height = imageHeight + 'px';
image.style.paddingTop = padding + 'px';
image.style.paddingBottom = padding + 'px';
frame.style.height = rowHeight + 'px';
carousel.insertBefore(frame, image);
frame.appendChild(image);
}
Carousel.rowHeight = carousel.getElementsByTagName('div')[0].offsetHeight;
carousel.style.height = Carousel.numVisible * Carousel.rowHeight + 'px';
carousel.style.visibility = 'visible';
var wrapper = Carousel.wrapper = document.createElement('div');
wrapper.id = 'carouselWrapper';
wrapper.style.width = carousel.offsetWidth + 'px';
wrapper.style.height = carousel.offsetHeight + 'px';
carousel.parentNode.insertBefore(wrapper, carousel);
wrapper.appendChild(carousel);
var prevButton = document.getElementById('prev'),
nextButton = document.getElementById('next');
prevButton.onclick = function () {
prevButton.disabled = nextButton.disabled = true;
rotateForward();
animate(-Carousel.rowHeight, 0, function () {
carousel.style.top = '0';
prevButton.disabled = nextButton.disabled = false;
});
};
nextButton.onclick = function () {
prevButton.disabled = nextButton.disabled = true;
animate(0, -Carousel.rowHeight, function () {
rotateBackward();
carousel.style.top = '0';
prevButton.disabled = nextButton.disabled = false;
});
};
};
body {
font-family: sans-serif;
}
.buttons {
margin: 5px 0;
}
button {
font-size: 14px;
display: inline;
padding: 3px 6px;
border: 2px solid #ccc;
background: #fff;
border-radius: 5px;
outline: none;
}
button:hover {
border: 2px solid #888;
background: #ffe;
cursor: pointer;
}
#carouselWrapper {
position: relative;
overflow: hidden;
}
#carousel {
position: absolute;
visibility: hidden;
}
<div id="spinner">
Loading...
</div>
<div id="carousel">
<img src="http://malsup.github.io/images/beach1.jpg">
<img src="http://malsup.github.io/images/beach2.jpg">
<img src="http://malsup.github.io/images/beach3.jpg">
<img src="http://malsup.github.io/images/beach4.jpg">
<img src="http://malsup.github.io/images/beach5.jpg">
<img src="http://malsup.github.io/images/beach9.jpg">
</div>
<div class="buttons">
<button id="prev">↑ Prev</button>
<button id="next">↓ Next</button>
</div>