Lightbox Slider en Vanilla JavaScript

Tiempo de ejecución: 30 minutos. Empezar

Autor: aderaaij
Views Total: 2,206
Sitio oficial: Ir a la web
Actualizado: October 3, 2017
Licencia: MIT

Vista prévia

Lightbox Slider en Vanilla JavaScript

Descripción

Este es un deslizador de lightbox de JavaScript de vainilla donde las imágenes se abrirán en una caja de luz de pantalla completa responsiva con la capacidad de desplazarse a través de todas las imágenes.

Más características

  • Carga diferida de imagen.
  • Velocidad de animación configurable.
  • Flechas de navegación.
  • Se admiten eventos de teclado/toque.

Funcionamiento

Cree una galería de miniaturas a partir de una lista HTML normal de la siguiente manera:

<ul>

<li class="gallery__item">


<a class="gallery__itemLink" href="1.jpg" data-rel="aiLightbox">



<img class="gallery__itemThumb" src="thumb-1.jpg">


</a>

</li>

<li class="gallery__item">


<a class="gallery__itemLink" href="1.jpg" data-rel="aiLightbox">



<img class="gallery__itemThumb" src="thumb-2.jpg">


</a>

</li>

<li class="gallery__item">


<a class="gallery__itemLink" href="1.jpg" data-rel="aiLightbox">



<img class="gallery__itemThumb" src="thumb-3.jpg">


</a>

</li>

<li class="gallery__item">


<a class="gallery__itemLink" href="1.jpg" data-rel="aiLightbox">



<img class="gallery__itemThumb" src="thumb-4.jpg">


</a>

</li>

...
</ul>

Los estilos CSS primarios para el control deslizante lightbox.

.gallery ul {

list-style: none;

margin: 0;

padding: 0;

width: 100%;

display: -webkit-box;

display: -ms-flexbox;

display: flex;

-webkit-box-pack: justify;

-ms-flex-pack: justify;

justify-content: space-between;

-ms-flex-wrap: wrap;

flex-wrap: wrap;
}

.gallery li {

margin-bottom: 1em;

border-radius: 3px;

box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);

-webkit-transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);

transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}

.gallery li:hover { box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); }

.gallery img {

display: block;

border-radius: 3px;
}

.m-lightbox {

position: fixed;

top: 0;

left: 0;

width: 100vw;

height: 100vh;

background: rgba(255, 255, 255, 0.9);

z-index: 1;

opacity: 0;

-webkit-transform: scale(0.8);

transform: scale(0.8);

-webkit-transition: opacity 0.3s ease-out, -webkit-transform 0.3s ease-out;

transition: opacity 0.3s ease-out, -webkit-transform 0.3s ease-out;

transition: opacity 0.3s ease-out, transform 0.3s ease-out;

transition: opacity 0.3s ease-out, transform 0.3s ease-out, -webkit-transform 0.3s ease-out;

pointer-events: none;
}

.m-lightbox.is-active {

opacity: 1;

-webkit-transform: scale(1);

transform: scale(1);

z-index: 101;

pointer-events: auto;
}

.m-lightbox__slider {

list-style: none;

margin: 0;

padding: 0;

width: 100vw;

height: 100vh;
}

.m-lightbox__slide {

position: absolute;

top: 0;

left: 0;

width: 100vw;

height: 100vh;

display: -webkit-box;

display: -ms-flexbox;

display: flex;

-webkit-box-pack: center;

-ms-flex-pack: center;

justify-content: center;

-webkit-box-align: center;

-ms-flex-align: center;

align-items: center;
}

.m-lightbox__slide img {

display: block;

max-width: calc(100vw - 2em);

max-height: 90vh;

opacity: 0;

-webkit-transition: opacity 0.3s ease;

transition: opacity 0.3s ease;
}

@media (min-width: 768px) {

.m-lightbox__slide img {

max-width: calc(100vw - 116px);

max-height: 90vh;
}
}

.m-lightbox__slide.is-loaded.is-active img { opacity: 1; }

.m-lightbox__slide.is-loaded.is-active .spinner { display: none; }

.m-lightbox button {

position: absolute;

margin: 0;

padding: 0;

z-index: 102;

background: transparent;

border: none;

cursor: pointer;
}

.m-lightbox__close {

top: 1em;

right: 1em;
}

.m-lightbox__nextPrev {

top: 50%;

-webkit-transform: translateY(-50%);

transform: translateY(-50%);

width: 42px;

height: 42px;

visibility: hidden;

opacity: 0;

-webkit-transform: scale(0.5);

transform: scale(0.5);

-webkit-transition: opacity 0.3s ease-out, -webkit-transform 0.3s ease-out;

transition: opacity 0.3s ease-out, -webkit-transform 0.3s ease-out;

transition: opacity 0.3s ease-out, transform 0.3s ease-out;

transition: opacity 0.3s ease-out, transform 0.3s ease-out, -webkit-transform 0.3s ease-out;
}

.m-lightbox__nextPrev.is-active {

visibility: hidden;

-webkit-transform: scale(1);

transform: scale(1);

opacity: 1;
}

@media (min-width: 1024px) {

.m-lightbox__nextPrev.is-active { visibility: visible; }
}

.m-lightbox__nextPrev svg {

display: block;

width: 100%;

height: auto;
}

.m-lightbox__nextPrev--next { right: 1em; }

.m-lightbox__nextPrev--prev { left: 1em; }

.m-lightbox__nextPrev:hover { cursor: pointer; }

.m-lightbox__counter {

position: absolute;

bottom: 1em;

left: 50%;

-webkit-transform: translateX(-50%);

transform: translateX(-50%);

color: #333;

font-weight: 700;
}

Style & animar el Spinner mientras se cargan las imágenes grandes.

.spinner {

width: 40px;

height: 40px;

position: absolute;

top: 50%;

left: 50%;

-webkit-transform: translateY(-50%) translateX(-50%);





transform: translateY(-50%) translateX(-50%);
}

.spinner::before, .spinner::after {

content: '';

width: 100%;

height: 100%;

border-radius: 50%;

background-color: #333;

opacity: 0.6;

position: absolute;

top: 0;

left: 0;

-webkit-animation: sk-bounce 2.0s infinite ease-in-out;





animation: sk-bounce 2.0s infinite ease-in-out;
}

.spinner::after {

-webkit-animation-delay: -1.0s;





animation-delay: -1.0s;
}

@-webkit-keyframes sk-bounce {

0%, 100% {


-webkit-transform: scale(0);






transform: scale(0);

}

50% {


-webkit-transform: scale(1);






transform: scale(1);

}
}

@keyframes sk-bounce {

0%, 100% {


-webkit-transform: scale(0);






transform: scale(0);

}

50% {


-webkit-transform: scale(1);






transform: scale(1);

}
}

Cargue la biblioteca swipe. js para el soporte de barrido táctil.

<script src="Swipe.js"></script>

La función principal.

'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

var _class, _temp, _initialiseProps;

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) {if (window.CP.shouldStopExecution(1)){break;} if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; }
window.CP.exitedLoop(1);
 return target; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Lightbox = (_temp = _class = function Lightbox(_ref) {


var _ref$lazyload = _ref.lazyload;


var lazyload = _ref$lazyload === undefined ? true : _ref$lazyload;


var _ref$counter = _ref.counter;


var counter = _ref$counter === undefined ? true : _ref$counter;


var _ref$arrows = _ref.arrows;


var arrows = _ref$arrows === undefined ? true : _ref$arrows;


var _ref$slideSpeed = _ref.slideSpeed;


var slideSpeed = _ref$slideSpeed === undefined ? 400 : _ref$slideSpeed;



var options = _objectWithoutProperties(_ref, ['lazyload', 'counter', 'arrows', 'slideSpeed']);



_classCallCheck(this, Lightbox);



_initialiseProps.call(this);



if (!options.selector) {




console.error('Please add a valid css selector with the option "selector:"');


} else if (typeof options.selector !== 'string') {




console.error(options.selector, 'is not a string but a(n) ' + _typeof(options.selector));


} else {




this.selector = options.selector;




this.lazyload = lazyload;




this.counter = counter;




this.arrows = arrows;




this.slideSpeed = slideSpeed;





this.links = Array.from(document.querySelectorAll('a' + options.selector));




this.offsets = [];




this.nodes = {};




this.imageIndex = null;




if (this.links.length > 0) {






this.createLightbox();






this.createNodes();






this.eventListeners(this.links);




} else {






console.error('The selector \'' + this.selector + '\' did not yield results. Please make sure the selector is applied on an \'a\' element.');




}


}
}, _initialiseProps = function _initialiseProps() {


var _this = this;



this.goTo = function (num, event) {




var _nodes = _this.nodes;




var items = _nodes.items;




var counter = _nodes.counter;




var lightboxNode = _nodes.lightboxNode;





if (_this.counter) {






counter.innerHTML = num + 1 + '/' + _this.links.length;




}




var spinner = '<div class="spinner"></div>';




var img = items[num].querySelector('img');




if (_this.lazyload) {






var src = img.getAttribute('data-src');






items[num].insertAdjacentHTML('beforeend', spinner);






// Set image attribute






img.setAttribute('src', src);







// Add class to slide item when image is completely loaded. Must be in this order.






var imgLoad = new Image();






imgLoad.onload = function () {








items[num].classList.add('is-active');








items[num].classList.add('is-loaded');






};






imgLoad.src = src;




} else {






items[num].classList.add('is-active');






items[num].classList.add('is-loaded');




}





// Change the offset for each slide based on its index and the current index.




for (var i = 0; i < _this.offsets.length; i++) {if (window.CP.shouldStopExecution(2)){break;}






var offset = _this.offsets[i] - num * 100;







items[i].style.transform = 'translateX(' + offset + 'vw)';







// Add transition type based on which event was triggered






if (event) {








if (event.target.className === 'gallery__itemThumb') {










items[i].style.transition = 'opacity 0.4s ease';








} else {










items[i].style.transition = 'transform ' + _this.slideSpeed + 'ms ease-out';








}






}




}
window.CP.exitedLoop(2);



};



this.createNodes = function (links) {




// Find all the lightbox nodes and add them to an object




Object.assign(_this.nodes, {






lightboxNode: document.querySelector('.m-lightbox'),






items: Array.from(document.querySelectorAll('.m-lightbox__slide')),






next: document.querySelector('.m-lightbox__nextPrev--next'),






prev: document.querySelector('.m-lightbox__nextPrev--prev'),






close: document.querySelector('.m-lightbox__close')





});





Object.assign(_this.nodes, {






counter: document.querySelector('.m-lightbox__counter')




});


};



this.eventListeners = function (links) {




var _nodes2 = _this.nodes;




var lightboxNode = _nodes2.lightboxNode;




var items = _nodes2.items;




var next = _nodes2.next;




var prev = _nodes2.prev;




var close = _nodes2.close;





links.forEach(function (item, index) {






item.addEventListener('click', function (e) {








e.preventDefault();








lightboxNode.classList.add('is-active');








document.body.style.overflow = 'hidden';








_this.imageIndex = index;








_this.goTo(index, e);








_this.setNav(index);






});




});





next.addEventListener('click', function (e) {






_this.goToNext(e);




});





prev.addEventListener('click', function (e) {






_this.goToPrev(e);




});





close.addEventListener('click', function () {






_this.closeBox();




});





document.onkeydown = function (e) {






switch (e.keyCode) {








case 37:










_this.goToPrev(e);










break;








case 39:










_this.goToNext(e);










break;








case 27:










_this.closeBox();










break;






};




};





items.forEach(function (item) {






// https://gist.github.com/Tam/d44c87b3daeb07b15984ddc6127d4e34






new Swipe(item.querySelector('img'), function (e, direction) {








e.preventDefault();








switch (direction) {










case "up":












// Handle Swipe Up












break;










case "down":












// Handle Swipe Down












break;










case "left":












_this.goToNext(e);












break;










case "right":












_this.goToPrev(e);












break;








}






});




});


};



this.setNav = function (index) {




if (_this.arrows) {






var _nodes3 = _this.nodes;






var next = _nodes3.next;






var prev = _nodes3.prev;







if (index < _this.links.length - 1) {








next.classList.add('is-active');






}






if (index >= _this.links.length - 1) {








next.classList.remove('is-active');






}






if (index > 0) {








prev.classList.add('is-active');






}






if (index <= 0) {








prev.classList.remove('is-active');






}




}


};



this.goToNext = function (e) {




var items = _this.nodes.items;





if (_this.imageIndex < items.length - 1) {






_this.goTo(_this.imageIndex + 1, e);






setTimeout(function () {








items[_this.imageIndex - 1].classList.remove('is-active');






}, _this.slideSpeed);






_this.imageIndex += 1;






_this.setNav(_this.imageIndex);




}


};



this.goToPrev = function (e) {




var items = _this.nodes.items;





if (_this.imageIndex > 0) {






_this.goTo(_this.imageIndex - 1, e);






setTimeout(function () {








items[_this.imageIndex + 1].classList.remove('is-active');






}, _this.slideSpeed);






_this.imageIndex -= 1;






_this.setNav(_this.imageIndex);




}


};



this.closeBox = function () {




var _nodes4 = _this.nodes;




var lightboxNode = _nodes4.lightboxNode;




var items = _nodes4.items;





lightboxNode.classList.remove('is-active');




document.body.style.overflow = 'auto';




setTimeout(function () {






items.forEach(function (item) {








return item.classList.remove('is-active');






});




}, _this.slideSpeed);


};



this.renderImages = function (images) {




var imagesLinks = images.map(function (item, index) {






var offset = index * 100;






_this.offsets.push(offset);






var imageSrc = item.getAttribute('href');






return '\n







<li class=\'m-lightbox__slide\' style=\'transform: translateX(' + offset + 'vw)\'>\n









' + (_this.lazyload ? '\n











<img data-src=\'' + imageSrc + '\'/>\n









' : '\n











<img src=\'' + imageSrc + '\'/>\n









') + '\n







</li>\n





';




});




return imagesLinks;


};



this.createLightbox = function () {




var lightbox = '\n





<div class=\'m-lightbox\'>\n







<div class=\'m-lightbox__controls\'>\n









<button class=\'m-lightbox__close\'>\n











<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">\n













<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>\n













<path d="M0 0h24v24H0z" fill="none"/>\n











</svg>\n









</button>\n









<button class=\'m-lightbox__nextPrev m-lightbox__nextPrev--prev\'>\n











<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">\n













<path d="M0 0h24v24H0z" fill="none"/>\n













<path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/>\n











</svg>\n









</button>\n









<button class=\'m-lightbox__nextPrev m-lightbox__nextPrev--next\'>\n











<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">\n













<path d="M0 0h24v24H0z" fill="none"/>\n













<path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/>\n











</svg>\n









</button>\n







</div>\n







<ul class=\'m-lightBox__slider\'>\n









' + _this.renderImages(_this.links).join('') + '\n







</ul>\n







<div class=\'m-lightbox__counter\'>\n







</div>\n





</div>\n



';




document.body.insertAdjacentHTML('beforeend', lightbox);


};
}, _temp);

Active el control deslizante de lightbox con los ajustes.

var lb = new Lightbox({


selector: '[data-rel="aiLightbox"]', // string


lazyload: true, // boolean


arrows: true, // boolean


counter: true, // boolean


slideSpeed: 500
 });

Te puede interesar: