Skapa bildgalleri med ren JavaScript

I den här handledningen skall vi skapa ett bildgalleri (lightbox) med ren JavaScript. Ett modalt bildgalleri används för att visa bilder i fullskärm i en överliggande ruta på den aktuella sidan.

Denna plugin är beroende av annytab.effects (Rena JavaScript-effekter) som vi har skrivit om i ett tidigare blogginlägg och Font Awesome för ikoner.

Vi ska skapa ett bildgalleri som kan användas för att visa en eller flera bilder i ett modalfönster. Bilder i samma grupp kan ha ett bildspel och bildgalleriet har sidhantering om det finns mer än en bild i en grupp. Bilder kan också ha en bildtext som visas längst ner i rutan. Modalrutan kan stängas genom att klicka utanför rutan (tillval) eller genom att klicka på x:et i övre högra hörnet.

Det här tillägget har testats och fungerar med Google Chrome (75.0.3770.100), Mozilla Firefox (67.0.4), Microsoft Edge (42.17134.1.0) och Internet Explorer (11.829.17134.0), detta utan någon polyfill. Om du vill stödja äldre webbläsare kan du läsa vårt inlägg om transpilering och komplettering av JavaScript.

Bildgalleri

Utseende (CSS)

Rutan är centrerad på skärmen och stängnings-knappen är skapad i ren CSS. Vi använder Font Awesome för ikoner.

/* Annytab lightbox*/
.annytab-lightbox-container {
    display: none;
    z-index: 100;
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    text-align: center;
    background-color: #000000;
    background-color: rgba(0, 0, 0, 0.7);
}
.annytab-lightbox-margin {
    display: block;
    margin: 40px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.annytab-lightbox-wrapper {
    display: inline-block;
    position: relative;
    max-width: 100%;
    background-color: #ffffff;
    border-radius: 8px;
    top: calc(50vh - 50px); /* adjust for margin */
    -ms-transform: translateY(-50%);
    transform: translateY(-50%);
}
.annytab-lightbox-padding {
    display: block;
    padding: 10px;
}
.annytab-lightbox-image {
    display: inline-block;
    max-width: 100%;
    max-height: calc(100vh - 100px); /* margin + padding */
    padding: 0;
    margin: 0; 
}
.annytab-lightbox-left-arrow {
    display: block;
    z-index: inherit;
    position: absolute;
    left: 20px;
    top: 50%;
    margin-top: -16px;
    cursor: pointer;
    width: 32px;
    height: 32px;
    border-radius: 4px;
    background-color: #000000;
    opacity: 0.5;
    filter: alpha(opacity=50);
    font-size: 30px;
    line-height: 32px;
    color: #ffffff;
}
.annytab-lightbox-right-arrow {
    display: block;
    z-index: inherit;
    position: absolute;
    right: 20px;
    top: 50%;
    margin-top: -16px;
    cursor: pointer;
    width: 32px;
    height: 32px;
    border-radius: 4px;
    background-color: #000000;
    opacity: 0.5;
    filter: alpha(opacity=50);
    font-size: 30px;
    line-height: 32px;
    color: #ffffff;
}
.annytab-lightbox-caption {
    display: none;
    position: absolute;
    bottom: 15px;
    left: 10px;
    right: 10px;
    max-height: 36px;
    overflow-y: auto;
    background-color: #000000;
    opacity: 0.6;
    filter: alpha(opacity=60);
    padding: 10px;
    color: #ffffff;
    text-align: left;
}
.annytab-lightbox-close {
    position: absolute;
    width: 24px;
    height: 24px;
    top: 8px;
    right: 8px;
    cursor: pointer;
    opacity: 0.6;
    filter: alpha(opacity=60);
}

.annytab-lightbox-close:hover {
    opacity: 1;
    filter: alpha(opacity=100);
}

.annytab-lightbox-close:before, .annytab-lightbox-close:after {
    position: absolute;
    right: 12px;
    content: ' ';
    height: 24px;
    width: 2px;
    background-color: #ffffff;
}

.annytab-lightbox-close:before {
    transform: rotate(45deg);
}

.annytab-lightbox-close:after {
    transform: rotate(-45deg);
}

JavaScript

Denna plugin har en konstruktor som tar alternativ som en parameter. Vi lägger till klickhändelser för alla länkar med en given väljare (selector) och det här tillägget har två offentliga metoder, open och close, som kan anropas från dina skript.

var annytab = annytab || {};
annytab.lightbox = (function () {

    'use_strict';

    // Constructor
    function lightbox(opts)
    {
        // Set default values for parameters
        opts = opts || {};

        // Set options
        this.options = { selector: '.annytab-lightbox-popup', fade_duration: 1000, close_click_outside: true, slideshow: true, slideshow_interval: 10000 };
        for (var option in this.options) {
            if (opts.hasOwnProperty(option) === true) {
                this.options[option] = opts[option];
            }
        }

        // Set variables
        resetVariables(this);

        // Get all links that should have a lightbox
        var links = document.querySelectorAll(this.options.selector);

        // Add events
        addLinkEvents(this, links);

    } // End of the constructor

    // Reset variables to default values
    function resetVariables(lb)
    {
        lb.current_slide = null;
        lb.last_slide = null;
        lb.container = null;
        lb.wrapper = null;
        lb.close_button = null;
        lb.automatic_slideshow = null;
        lb.left_arrow = null;
        lb.right_arrow = null;
        lb.caption_container = null;

    } // End of the resetVariables method

    // Add events
    function addLinkEvents(lb, links)
    {
        // Loop links
        for (var i = 0; i < links.length; i++)
        {
            // Add a click event
            window.onload = links[i].addEventListener('click', function (event) {

                // Prevent default click behaviour
                event.preventDefault();

                // Open the lightbox
                lb.open(this);

            }, false);
        }

    } // End of the addLinkEvents method

    // Add container events
    function addContainerEvents(lb)
    {
        // Add a close event
        window.onload = lb.close_button.addEventListener('click', function (event) {

            // Prevent default click behaviour
            event.preventDefault();

            // Close the lightbox
            lb.close();

        }, false);

        // Add a close event
        if (lb.options.close_click_outside === true)
        {
            window.onload = lb.container.addEventListener('click', function (event) {

                // Prevent default click behaviour
                event.preventDefault();

                // Close the lightbox
                if (event.target.contains(lb.wrapper) === true)
                {
                    lb.close();
                }

            }, false);
        }

        // Add paging if there is more than 1 slide
        if (lb.last_slide > 0)
        {
            // Show arrows
            lb.left_arrow.style.display = 'block';
            lb.right_arrow.style.display = 'block';

            // Add left arrow click event
            window.onload = lb.left_arrow.addEventListener('click', function (event) {

                // Prevent default click behaviour
                event.preventDefault();

                // Show the previous slide
                lb.showSlide(-1);

                // Turn of the slideshow
                clearInterval(lb.automatic_slideshow);

            }, false);

            // Add right arrow click event
            window.onload = lb.right_arrow.addEventListener('click', function (event) {

                // Prevent default click behaviour
                event.preventDefault();

                // Show the next slide
                lb.showSlide(1);

                // Turn of the slideshow
                clearInterval(lb.automatic_slideshow);

            }, false);

            // Create a slideshow
            if (lb.options.slideshow === true)
            {
                lb.automatic_slideshow = setInterval(function () { lb.showSlide(1); }, lb.options.slideshow_interval);
            }
        }
        else
        {
            // Hide arrows
            lb.left_arrow.style.display = 'none';
            lb.right_arrow.style.display = 'none';
        }

    } // End of the addContainerEvents method

    // Show a slide
    lightbox.prototype.showSlide = function (step)
    {
        // Set the current slide
        this.current_slide += step;

        // Make sure that the slide id not is outside borders
        if (this.current_slide > this.last_slide) {
            this.current_slide = parseInt(0);
        }
        if (this.current_slide < 0) {
            this.current_slide = parseInt(this.last_slide);
        }

        // Get slides
        var slides = this.container.querySelectorAll('.annytab-lightbox-image');
        var next_slide = this.container.querySelector('img[data-lightbox-id="' + this.current_slide + '"]');

        // Set a caption
        var caption = next_slide.getAttribute('data-lightbox-caption');
        if (caption !== null)
        {
            this.caption_container.innerHTML = caption;
            this.caption_container.style.display = 'block';
        }
        else
        {
            this.caption_container.style.display = 'none';
        }

        // Hide slides
        for (var i = 0; i < slides.length; i++)
        {
            slides[i].style.display = 'none';
        }

        // Fade in the next slide
        annytab.effects.fadeIn(next_slide, this.options.fade_duration, 'inline-block');

    }; // End of the showSlide method

    // Open a lightbox
    lightbox.prototype.open = function (link)
    {
        // Get the href attribute
        var href = link.getAttribute('href');

        // Get the group
        var group = link.getAttribute('data-lightbox-group');

        // Get the caption
        var caption = link.getAttribute('data-lightbox-caption');

        // Add the first image
        var source = '<img data-lightbox-id="0" src="' + href + '" class="annytab-lightbox-image" alt="image" style="display:none;"';
        source += caption !== null ? ' data-lightbox-caption="' + caption : '';
        source += '" />';

        // Create a counter
        var counter = 1;

        // Find all images in the group
        var images = document.querySelectorAll('[data-lightbox-group="' + group + '"]');

        // Loop images
        for (var i = 0; i < images.length; i++)
        {
            var url = images[i].getAttribute('href');
            if (url !== href)
            {
                source += '<img data-lightbox-id="' + counter + '" src="' + url + '" class="annytab-lightbox-image" alt="image" style="display:none;"';
                source += images[i].getAttribute('data-lightbox-caption') !== null ? ' data-lightbox-caption="' + images[i].getAttribute('data-lightbox-caption') : '';
                source += '" />';
                counter += 1;
            }
        }
        
        // Get the last slide and set the current slide
        this.last_slide = counter - 1;
        this.current_slide = parseInt(-1);

        // Create a lightbox
        this.container = document.createElement('div');
        this.container.setAttribute('class', 'annytab-lightbox-container');
        this.container.insertAdjacentHTML('beforeend', '<div class="annytab-lightbox-margin">'
            + '<div class="annytab-lightbox-wrapper">'
            + '<div class="annytab-lightbox-padding">'
            + source
            + '<div class="annytab-lightbox-left-arrow"><i class="fas fa-angle-left"></i></div>'
            + '<div class="annytab-lightbox-right-arrow"><i class="fas fa-angle-right"></i></div>'
            + '<div class="annytab-lightbox-caption"></div>'
            + '</div></div></div>'
            + '<div class="annytab-lightbox-close"></div >');
        document.body.appendChild(this.container);

        // Get references
        this.wrapper = this.container.querySelector('.annytab-lightbox-wrapper');
        this.close_button = this.container.querySelector('.annytab-lightbox-close');
        this.caption_container = this.container.querySelector('.annytab-lightbox-caption');
        this.left_arrow = this.container.querySelector('.annytab-lightbox-left-arrow');
        this.right_arrow = this.container.querySelector('.annytab-lightbox-right-arrow');

        // Fade in the container
        annytab.effects.fadeIn(this.container, this.options.fade_duration, 'block');

        // Add container events
        addContainerEvents(this);

        // Show the next slide
        this.showSlide(1);

    }; // End of the open method

    // Close a lightbox
    lightbox.prototype.close = function () {

        // Turn of the slideshow
        clearInterval(this.automatic_slideshow);

        // Fade out the container
        annytab.effects.fadeOut(this.container, this.options.fade_duration);

        // Remove the container
        var box = this.container;
        setTimeout(function ()
        {
            document.body.removeChild(box);

        }, this.options.fade_duration);

        // Reset variables (GC)
        resetVariables(this);

    }; // End of the close method

    // Return this object
    return lightbox;

})();

Så här använder du denna plugin

Lägg till en länk runt bilder som ska ha ett bildgalleri, ange ett data-lightbox-group attribut (valfritt) för bilder som ska ingå i en grupp och ange ett attribut för data-lightbox-caption (valfritt) om du vill att en bildtext ska visas över bilden. Vi har använt en klass som väljare (selector), det kan vara en klass, en tagg eller ett namn.

<a href="/images/background_large.jpg" class="annytab-lightbox-popup" data-lightbox-group="gp1" data-lightbox-caption="Hello, I am the one how have taken this photo.">
    <img src="/images/background_small.jpg" alt="Background image" style="max-width:100%;border:1px solid #cccccc;" />
</a>
<a href="/images/logotype_large.jpg" class="annytab-lightbox-popup" data-lightbox-group="gp1">
    <img src="/images/logotype_small.jpg" alt="Background image" style="max-width:100%;border:1px solid #cccccc;" />
</a>

@*Open and close from JavaScript*@
<div id="testLink" href="/images/background_large.jpg"></div>
<div onclick="openLink()">Open link</div>
<div style="position:absolute;z-index:500;font-size:36px;margin-top:50px;" onclick="closeBox()">Close box</div>

Skapa en ny instans av denna plugin inuti en skript-tagg och lägg till alternativ som en parameter. Bildgalleri läggs till för alla länkar med den valda väljaren, du kan manuellt anropa metoden open och metoden close från skript om du vill.

<script src="js/font-awesome/v5.3.1/all.min.js"></script>
<script src="/js/annytab-shared/annytab.effects.js"></script>
<script src="/js/annytab-shared/annytab.lightbox.js"></script>
<script>

    // Lightbox
    var lightbox = new annytab.lightbox({ selector: '.annytab-lightbox-popup', fade_duration: 1000, close_click_outside: true, slideshow: true, slideshow_interval: 10000 });

    // Open lightbox
    function openLink() { lightbox.open(document.getElementById('testLink')); }

    // Close lightbox
    function closeBox() { console.log('Closing'); lightbox.close(); }

</script>

Lämna ett svar

E-postadressen publiceras inte. Obligatoriska fält är märkta *