Кодимо прев'ю завантаження зображень
12 Вересня 2019
наступна стаття
Ми не будемо довго пояснювати причини, що спонукали до створення даної статті. Можливість швидко та зручно оперувати зображеннями, що завантажуються на сайт, високо цінують усі замовники. І для них дуже важливо знати, як буде виглядати картинка вже на сайті. Отож, я пропоную на розсуд фронтенд-розробникам кастомний, зручний та швидкий спосіб для реалізації прев’юшки завантаженого зображення на веб-сторінці. Для найбільш нетерплячих — наприкінці статті ви знайдете вільне посилання на Codepen з готовим результатом.
Рекомендую приготувати каву/чай, оскільки заняття починається. Спершу створюємо html розмітку:
<div class="wrapper"> <div class="preview"></div> <label class="file"> <input type="file" name="files[0][]" accept="image/jpeg,image/png,image/gif,application/pdf,image/bmp"> <span>Додати зображення</span> </label> </div>
Результат:
Стилізуємо:
.preview { display: flex; max-width: 1200px; } .file { display: inline-block; padding: 15px 25px; margin: 15px; background-color: #333; color: #fff; cursor: pointer; } .uploaded { width: 25%; height: 250px; border-radius: 24px; border: 1px dashed #000; margin: 0 15px; overflow: hidden; position: relative; z-index: 1; } .uploaded img { width: 100%; height: 100%; object-fit: cover; display: block; } input { display: none; } .remove { position: absolute; z-index: 2; width: 20px; height: 20px; border-radius: 100%; background-color: #000; border: none; top: 15px; right: 15px; cursor: pointer; outline: none; } .remove:before { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(-45deg); width: 14px; height: 2px; background-color: #fff; } .remove:after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(45deg); width: 14px; height: 2px; background-color: #fff; }
Результат:

Переходимо до реалізації прев’ю файла.
Створюємо змінні з потрібними нам елементами, прелоудером та кнопкою видалення:
var preloaderFile ='<img class="preloader" src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif">';
var removeFile = '<button onclick="delFileFromInput()" class="remove"></button>';
Створюємо функцію “readURL” з перевіркою на завантаження файлу:
function readURL(input) { if (input.files && input.files[0]) { } }
Генеруємо новий інпут, в якому буде дублюватися завантажений файл, та прописуємо йому потрібні атрибути:
function readURL(input) { if (input.files && input.files[0]) { var mass = ["image/jpeg", "image/jpg", "image/png", "image/gif", "application/pdf", "image/bmp"]; var nt = document.createElement('input'); nt.setAttribute("type", "file"); var index = $(input).closest('.wrapper').index(); nt.setAttribute("name", 'files['+index+'][]'); if($(input).data('name')){ nt.setAttribute("name", $(input).attr('name')); nt.setAttribute("data-name", true); } nt.setAttribute("accept", "image/jpeg,image/png,image/gif,application/pdf,image/bmp"); } }
Після цього створюємо об'єкт “FileReader()”, вибираємо метод читання файлу “readAsDataURL” і при його завантаженні (reader.onload), створюємо обгортку нашої прев’юшки (uploaded) та зображення (img) з результатом читання файлу (e.target.result).
function readURL(input) { if (input.files && input.files[0]) { var mass = ["image/jpeg", "image/jpg", "image/png", "image/gif", "application/pdf", "image/bmp"]; var nt = document.createElement('input'); nt.setAttribute("type", "file"); var index = $(input).closest('.wrapper').index(); nt.setAttribute("name", 'files['+index+'][]'); if($(input).data('name')){ nt.setAttribute("name", $(input).attr('name')); nt.setAttribute("data-name", true); } nt.setAttribute("accept", "image/jpeg,image/png,image/gif,application/pdf,image/bmp"); var reader = new FileReader(); reader.onload = function (e) { var div = document.createElement('div'); $(div).addClass('uploaded'); var img = document.createElement('img'); var typec = input.files[0].type; var size = input.files[0].size; $(img).attr('src', e.target.result); } reader.readAsDataURL(input.files[0]); } }
Залишаєть зробити перевірку на правильність файлу та генерацію html.
Для цього створюємо дві функції та декілька перевірок:
// генерації html function acceptung() { $(div).append(preloaderFile); $(div).append(img); $(div).append(removeFile); $(input).closest('.wrapper').find('.preview').append(div); $(input).closest('label').prepend(nt); $(div).append(input); setTimeout(function() { $(div).find('.preloader').remove(); }, 500) } // видалення файлу при помилці function declinetung() { $(input).closest('label').prepend(nt); $(input).remove(); } // перевірка на тип та розмір файлу if(typec == "application/pdf"){ if(size > 11000000){ declinetung(); alert('max size pdf 10Mb'); }else{ $(img).attr('src', 'images/pdff.jpg'); acceptung(); } }else if($.inArray(typec, mass) == -1 ){ declinetung(); }else if(size > 6100000){ declinetung(); alert('max size image 6Mb'); }else{ acceptung(); }
Доробляємо функціонал для видалення файлу:
function delFileFromInput() { $(document).on('click', '.remove', function () { $(this).closest('.uploaded').remove(); }); }
Декларуємо нашу функцію “readURL” по зміні інпута:
$(document).on('change', '.file input',function(){ readURL(this); });
Все, наша прев’юшка готова)
Результат:
Повний код JavaScript:
var preloaderFile ='<img class="preloader" src="https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif">'; var removeFile = '<button onclick="delFileFromInput()" class="remove"></button>'; function readURL(input) { if (input.files && input.files[0]) { var mass = ["image/jpeg", "image/jpg", "image/png", "image/gif", "application/pdf", "image/bmp"]; var nt = document.createElement('input'); nt.setAttribute("type", "file"); var index = $(input).closest('.wrapper').index(); nt.setAttribute("name", 'files['+index+'][]'); if($(input).data('name')){ nt.setAttribute("name", $(input).attr('name')); nt.setAttribute("data-name", true); } nt.setAttribute("accept", "image/jpeg,image/png,image/gif,application/pdf,image/bmp"); var reader = new FileReader(); reader.onload = function (e) { var div = document.createElement('div'); $(div).addClass('uploaded'); var img = document.createElement('img'); var typec = input.files[0].type; var size = input.files[0].size; $(img).attr('src', e.target.result); function acceptung() { $(div).append(preloaderFile); $(div).append(img); $(div).append(removeFile); $(input).closest('.wrapper').find('.preview').append(div); $(input).closest('label').prepend(nt); $(div).append(input); setTimeout(function() { $(div).find('.preloader').remove(); }, 500) } function declinetung() { $(input).closest('label').prepend(nt); $(input).remove(); } if(typec == "application/pdf"){ if(size > 11000000){ declinetung(); alert('max size pdf 10Mb'); }else{ $(img).attr('src', 'images/pdff.jpg'); acceptung(); } }else if($.inArray(typec, mass) == -1 ){ declinetung(); }else if(size > 6100000){ declinetung(); alert('max size image 6Mb'); }else{ acceptung(); } } reader.readAsDataURL(input.files[0]); } } function delFileFromInput() { $(document).on('click', '.remove', function () { $(this).closest('.uploaded').remove(); }); } $(document).on('change', '.file input',function(){ readURL(this); });
Як і обіцяли: результат роботи на Codepen: https://codepen.io/approxua/pen/XWraJRE. Ми будемо раді вислухати пропозиції чи, можливо, зауваження до вищесказаного. А якщо все сподобалося — зробіть репост;)
Ми зв'яжемось з Вами протягом 10 хвилин