Menulis generator galeri gambar dengan bilah geser internal



Selamat siang teman!

Alih-alih pengantar (pernyataan masalah)


Semuanya dimulai dengan studi tentang slider orang lain (solusi siap pakai di jaringan, seperti bxslider , owlcarousel , dan slick ). Suatu hari saya akan menulis tutorial rinci tentang cara bekerja dengan alat-alat ini (mimpi indah). Ada keinginan untuk menulis slider Anda. Namun, segera (termasuk setelah membaca beberapa artikel tentang Habré), ia menyadari bahwa hanya slider untuk pengecut. Dibutuhkan sesuatu yang lebih radikal.

Sebagai hasilnya, saya datang dengan tugas berikut: untuk menulis generator galeri adaptif dengan slider bawaan.

Kondisi:

  • Kemampuan untuk mengunggah sejumlah gambar (dari mana saja di hard drive Anda).
  • Galeri ini terdiri dari gambar yang diunggah, markup dibentuk "on the fly" sesuai dengan semantik HTML5.
  • Galeri terlihat sama bagusnya di layar dengan resolusi berbeda.
  • Ketika Anda mengklik gambar apa pun, slider dihasilkan.
  • Saat membuat slider, latar belakang menjadi gelap.
  • Gambar yang diklik adalah slide pertama.
  • Pergeseran slide diimplementasikan melalui DOM.
  • Pergeseran slide dengan lancar.
  • Kemampuan untuk mengontrol perpindahan slide menggunakan tombol dan keyboard.
  • Kemampuan untuk kembali ke galeri dengan mengklik slide dan tombol saat ini, serta menggunakan keyboard.
  • JavaScript murni (semua markup melalui JS).
  • Kode minimum.

Jadi, ayo pergi (seperti yang dikatakan Gagarin, pergi ke luar angkasa).

Markupnya terlihat seperti ini:
<div class="wrap">
    <input type="file" multiple accept="image/*">
    <button>generate gallery</button>
</div>

Dari hal-hal yang menarik, mungkin, beberapa dan menerima atribut dari tag input. Atribut pertama memungkinkan Anda untuk mengunggah banyak file, yang kedua - menetapkan filter pada jenis file yang dapat diunduh. Dalam hal ini, accept memiliki nilai "image / *", artinya hanya gambar (apa saja) yang dapat diunggah.

Segera bawa kecantikan (tambahkan gaya):
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    min-height: 100vh;
    background: radial-gradient(circle, skyblue, steelblue);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

button {
    padding: 0.25em;
    font-family: monospace;
    text-transform: uppercase;
    cursor: pointer;
}

.darken {
    position: absolute;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.4);
    z-index: -1;
}

.slider {
    width: 100%;
    display: inherit;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}

figure {
    margin: 0.5em;
    width: 300px;
    display: inherit;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    transition: 0.2s;
}

figcaption {
    font-size: 1.2em;
    text-transform: capitalize;
    text-align: center;
    margin-bottom: 0.25em;
    color: #ddd;
    text-shadow: 1px 1px rgba(0, 0, 0, 0.4);
}

img {
    max-width: 80%;
    max-height: 80vh;
    cursor: pointer;
}

.button {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 30px;
    background: none;
    border: none;
    outline: none;
    filter: invert();
}

.left {
    left: 2em;
}

.right {
    right: 2em;
}

.close {
    top: 2em;
    right: 1em;
}


Tidak ada yang perlu dibicarakan (.darken - peredupan).

Pindah ... ke JS.

Kami menemukan tombol dan menggantung pendengar di atasnya:
let button = document.querySelector("button");
button.addEventListener("click", generateGallery);

Semua kode lebih lanjut akan berada dalam fungsi generateGallery untuk menghindari "tidak didefinisikan" tanpa kembali:
function generateGallery() {
    //    
}

Kami menemukan input, memeriksa apakah itu tidak kosong, mendapatkan koleksi file yang diunduh, menghapus .wrap dan membuat wadah untuk galeri:
let input = document.querySelector("input");
// ,  input  
if(input.files.length == 0) return;
let files = input.files;
//  
let i;

//  .wrap,     
let wrap = document.querySelector(".wrap");
document.body.removeChild(wrap);

//    , ,    gallery
let slider = document.createElement("div");
slider.className = "slider";
document.body.appendChild(slider);

Kami menyortir kumpulan file, mendapatkan nama dan alamat setiap file, membuat markup, membuat teks gambar dan gambar itu sendiri:
for (i = 0; i < files.length; i++) {
    let file = files[i];
    // URL.createObjectURL         ,         
    // ,   ,       
    //             ,      
    /*let src = URL.createObjectURL(file);*/

    //   
    let name = file.name;

    //   ,      img     
    let src = `img/${name}`;

    //  : figure, figcaption, img
    let figure = document.createElement("figure");
    slider.appendChild(figure);

    let figcaption = document.createElement("figcaption");

    //  ,             ,   
    // (?=\.) -  :     ,    
    //       \w,         
    let regexp = /.+(?=\.)/;
    name = name.match(regexp);
    //   ["", index: 0, input: ".jpg", groups: undefined]
    //    
    figcaption.innerText = name[0];
    figure.appendChild(figcaption);

    //  
    let img = document.createElement("img");
    img.src = src;
    figure.appendChild(img);
}

Kami ingin membuat bilah geser saat mengeklik gambar. Untuk melakukan ini, kami menemukan keseluruhan gambar dan menggantungnya di setiap pendengar:
let figures = document.querySelectorAll("figure");
for (i = 0; i < figures.length; i++) {
    let figure = figures[i];
    figure.addEventListener("click", () => {
        //  ,       figure,   
        generateSlider(figure);
    });
}

Selanjutnya, kami bekerja di dalam fungsi generateSlider:
function generateSlider(figure) {
    //  
}

Gelapkan latar belakang:
darkenBack();
function darkenBack() {
    // ,   
    //  , ,   , 
    if (document.querySelector(".darken") == null) {
        let div = document.createElement("div");
        div.className = "darken";
        document.body.appendChild(div);
    } else {
        let div = document.querySelector(".darken");
        document.body.removeChild(div);
    }
}

Kami akan menampilkan satu slide sekaligus. Jangan lupa bahwa sakelar geser harus halus. Ini mudah dicapai dengan transparansi dan transisi kecil. Oleh karena itu, kami menempatkan gambar di atas satu sama lain, menempatkannya di tengah, dan membuat semua gambar, kecuali yang "diklik", transparan:
for (i = 0; i < figures.length; i++) {
    if (figures[i].hasAttribute("style")) {
        figures[i].removeAttribute("style");
    } else {
        figures[i].setAttribute("style", "margin: 0; width: auto; position: absolute; opacity: 0;");
    }
}

//      / 
if (figure.hasAttribute("style")) {
    figure.style.opacity = 1;
    generateButtons();
} else generateButtons();

Selanjutnya, buat tombol untuk berganti slide dan tutup galeri. Kode tersebut ternyata panjang dan membosankan (mungkin menghasilkan tombol setiap kali Anda memulai slider bukan ide yang baik):
Kode pembuatan tombol:
function generateButtons() {
    if (document.querySelector(".buttons") == null) {
        //    
        let buttons = document.createElement("div");
        buttons.className = "buttons";
        slider.appendChild(buttons);

        //   
        let leftButton = document.createElement("button");
        leftButton.className = "button left";
        let leftImg = document.createElement("img");
        leftImg.src = "https://thebestcode.ru/media/sliderGenerator/buttons/left.png";
        leftButton.appendChild(leftImg);
        buttons.appendChild(leftButton);
        leftButton.addEventListener("click", () => changeSlide("-"));

        //   
        let rightButton = document.createElement("button");
        rightButton.className = "button right";
        let rightImg = document.createElement("img");
        rightImg.src = "https://thebestcode.ru/media/sliderGenerator/buttons/right.png";
        rightButton.appendChild(rightImg);
        buttons.appendChild(rightButton);
        rightButton.addEventListener("click", () => changeSlide("+"));

        //    
        let closeButton = document.createElement("button");
        closeButton.className = "button close";
        let closeImg = document.createElement("img");
        closeImg.src = "https://thebestcode.ru/media/sliderGenerator/buttons/close.png";
        closeButton.appendChild(closeImg);
        buttons.appendChild(closeButton);
        closeButton.addEventListener("click", () => generateSlider(figure));
    } else {
        //   ,  
        let buttons = document.querySelector(".buttons");
        slider.removeChild(buttons);
    }
}


Switching slide diimplementasikan menggunakan fungsi changeSlide, yang dikirimkan sebagai parameter, masing-masing, "+" atau "-":
function changeSlide(e) {
    //    
    for (i = 0; i < figures.length; i++) {
        figures[i].style.opacity = 0;
    }
    if (e == "-") {
        //      ,    
        if (figure == figures[0]) {
            figure = figures[figures.length - 1];
        } else {
            figure = figure.previousElementSibling;
        }
    } else if (e == "+") {
        //      ,    
        if (figure == figures[figures.length - 1]) {
            figure = figures[0];
        } else {
            figure = figure.nextElementSibling;
        }
    }
    //    
    figure.style.opacity = 1;
}

Tambahkan kemampuan untuk berganti slide dan tutup galeri menggunakan keyboard:
document.addEventListener("keydown", e => {
    //  
    if (e.keyCode == 37 || e.keyCode == 189) {
        changeSlide("-");
    //  
    } else if (e.keyCode == 39 || e.keyCode == 187) {
        changeSlide("+");
    // esc
    } else if(e.keyCode == 27) {
        generateSlider(figure);
    }
});

Itu saja, generator galeri adaptif dengan slider bawaan sudah siap. Misi selesai. Kondisi terpenuhi. Menjelang akhir, saya menyadari bahwa "kode minimum" dan "semua markup dibuat dengan menggunakan JS" saling bertentangan, tetapi sudah terlambat (apakah sudah terlambat untuk meminta maaf atau bagaimana dengan One Republic?).

Hasilnya bisa dilihat di sini .

Perhatikan bahwa pada Codepen kami menggunakan URL.createObjectURL untuk menautkan ke gambar, karena Codepen tidak melihat folder img.

Terima kasih atas perhatian Anda.

Source: https://habr.com/ru/post/undefined/


All Articles