Как реализовать поочерёдную загрузку изображений и их предпросмотр, и возможность удаления по кнопке?

Ссылка скопирована
1 ответ

Собственно, у меня есть сгенерированный код js для добавления в форму изображений пользователем и их предпросмотра. Но глобально есть две проблемы.
1) При удалении изображений по кнопке происходит смена индексов (то ли у файлов в input, то ли у кнопок внутри div`a class="image-preview") в связи с этим если удалять начиная с конца к началу по порядку, то всё отлично работает, но если делать с начала в конец или произвольно, то всегда остаётся 1-2 файла в input'е, хотя все изображения из предпросмотра удалены.
пример некорректной работы
Показывает что файла два, а изображение осталось одно.

Как реализовать поочерёдную загрузку изображений и их предпросмотр, и возможность удаления по кнопке?

Как реализовать поочерёдную загрузку изображений и их предпросмотр, и возможность удаления по кнопке?

2) Уже менее критично, но всё же хочу реализовать возможность поочерёдного добавления изображений, а то в текущем состоянии при добавлении новой картинки с помощью input старые файлы автоматически очищаются, а мне это не нужно, ведь для очищения у юзера будут специальные кнопки возле каждого изображения в контейнере предпросмотра. Очевидно нужно убрать очищение сгенерированного innerHtml внутри js функции, но непонятно как сделать так чтобы сохранялись не только картинки в контейнере предпросмотра, но и чтобы фактически файлы внутри input`a тоже сохранялись.

function checkFileCount(input) {     if (input.files.length > 5) {         alert("Вы можете выбрать не более пяти файлов."); //хочу чтобы пользователь не мог загрузить суммарно больше 5 файлов         input.value = ''; // очищаем значение поля input, чтобы пользователь мог выбрать файлы заново     } else {         previewImages(input); //вызываю функцию отвечающую за предпоказ      } }  function previewImages(input) {     var files = input.files;      var preview = document.querySelector('.image-preview');  //выбираем контейнер где будут отображаться картинки     preview.innerHTML = '';  //очищение этого контейнера от изображений загруженных в предыдущий раз   <b>//эту строку нужно будет закомментировать чтобы реализовать многократное добавление без очищения содержимого input, // но не всё так просто, проблема в том что закомментировав её старые изображения в предпросмотре будут сохраняться, // но в input эти старые изображения будут удалены (в пункте 2 говорил про это)</b>      for (var i = 0; i < files.length; i++) { //цикл для чтения изображений         var file = files[i];         var reader = new FileReader();         reader.onload = (function(file, index) {             return function(e) {                 var image = document.createElement('img');  //реализуем предпросмотр выбранных изображений                 image.src = e.target.result;                 image.classList.add('preview-image');                 preview.appendChild(image);                  var removeButton = document.createElement('button');  //кнопка удаления для каждого изображения                 removeButton.textContent = 'X';                 removeButton.classList.add('remove-button');                 removeButton.onclick = function() {  //добавляем функцию чтобы при нажатии на кнопку удалялись изображения из предпросмотра и из файлов input'a                     preview.removeChild(image);                     preview.removeChild(removeButton);                     // Удаляем файл из выбранных файлов                     input.files = removeFile(input.files, index);                 };                 preview.appendChild(removeButton);             };         })(file, i);          reader.readAsDataURL(file);      } }  <b>// Функция для удаления файла из списка файлов по индексу.  //В ней как раз таки зарыта собака, потому что после удаления одного из элементов // индексы других меняются и некоторые  дальнейшие удаления происходят некорректно, // хотя если удалять начиная с конца, то всё работает корректно (в пункте 1 писал об этом)</b> function removeFile(files, index) {     var newFiles = new DataTransfer();     for (var i = 0; i < files.length; i++) {         if (i !== index) {             newFiles.items.add(files[i]);         }     }     return newFiles.files; }

function checkFileCount(input) { if (input.files.length > 5) { alert("Вы можете выбрать не более пяти файлов."); //хочу чтобы пользователь не мог загрузить суммарно больше 5 файлов input.value = ''; // очищаем значение поля input, чтобы пользователь мог выбрать файлы заново } else { previewImages(input); //вызываю функцию отвечающую за предпоказ } } function previewImages(input) { var files = input.files; var preview = document.querySelector('.image-preview'); //выбираем контейнер где будут отображаться картинки preview.innerHTML = ''; //очищение этого контейнера от изображений загруженных в предыдущий раз <b>//эту строку нужно будет закомментировать чтобы реализовать многократное добавление без очищения содержимого input, // но не всё так просто, проблема в том что закомментировав её старые изображения в предпросмотре будут сохраняться, // но в input эти старые изображения будут удалены (в пункте 2 говорил про это)</b> for (var i = 0; i < files.length; i++) { //цикл для чтения изображений var file = files[i]; var reader = new FileReader(); reader.onload = (function(file, index) { return function(e) { var image = document.createElement('img'); //реализуем предпросмотр выбранных изображений image.src = e.target.result; image.classList.add('preview-image'); preview.appendChild(image); var removeButton = document.createElement('button'); //кнопка удаления для каждого изображения removeButton.textContent = 'X'; removeButton.classList.add('remove-button'); removeButton.onclick = function() { //добавляем функцию чтобы при нажатии на кнопку удалялись изображения из предпросмотра и из файлов input'a preview.removeChild(image); preview.removeChild(removeButton); // Удаляем файл из выбранных файлов input.files = removeFile(input.files, index); }; preview.appendChild(removeButton); }; })(file, i); reader.readAsDataURL(file); } } <b>// Функция для удаления файла из списка файлов по индексу. //В ней как раз таки зарыта собака, потому что после удаления одного из элементов // индексы других меняются и некоторые дальнейшие удаления происходят некорректно, // хотя если удалять начиная с конца, то всё работает корректно (в пункте 1 писал об этом)</b> function removeFile(files, index) { var newFiles = new DataTransfer(); for (var i = 0; i < files.length; i++) { if (i !== index) { newFiles.items.add(files[i]); } } return newFiles.files; }

<div class="cont">             <label class="filter" for="images">Додати фотографію</label>             <input type="file" id="images" name="images" accept="image/*" onchange="checkFileCount(this)" multiple required>         </div>

<div class="cont"> <label class="filter" for="images">Додати фотографію</label> <input type="file" id="images" name="images" accept="image/*" onchange="checkFileCount(this)" multiple required> </div>

Исходный html код

<!DOCTYPE html> <html> <head>     <meta charset="UTF-8">     <link rel="stylesheet" type="text/css" href="css/styles2.css">     <title>Add bus form</title> </head> <body>  <header>     <ul class="menu">     <div class="leftPart"><li id="findPet"><a href="/pets">Знайти тварину</a></li>     <li><a href="/rules">Правила адопції</a></li>     <li><a href="/help">Допомогти</a></li>     <li><a href="/aboutProject">Про проєкт</a></li> </div>     <div class="rightPart"><li id="createAdd"><a href="/myProfile">Додати оголошення</a></li>     <li id="login"><a href="/authorization">Профіль</a></li> </div> </ul> </header> <div class="center-global-container">             <div class="errorMessage">${errorMessage}</div>        <div class="filters">          <form class="addForm" action="/cats/add" method="post">             </div>          <div class="cont">             <label class="filter" for="images">Додати фотографію</label>             <input type="file" id="images" name="images" accept="image/*" onchange="checkFileCount(this)" multiple required>         </div>         <div class="image-preview"></div>         <button type="submit" name="sumbit" class="sumbit-form">Опублікувати оголошення</button>     </form>     </div> </div> </body> </html>

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="css/styles2.css"> <title>Add bus form</title> </head> <body> <header> <ul class="menu"> <div class="leftPart"><li id="findPet"><a href="/pets">Знайти тварину</a></li> <li><a href="/rules">Правила адопції</a></li> <li><a href="/help">Допомогти</a></li> <li><a href="/aboutProject">Про проєкт</a></li> </div> <div class="rightPart"><li id="createAdd"><a href="/myProfile">Додати оголошення</a></li> <li id="login"><a href="/authorization">Профіль</a></li> </div> </ul> </header> <div class="center-global-container"> <div class="errorMessage">${errorMessage}</div> <div class="filters"> <form class="addForm" action="/cats/add" method="post"> </div> <div class="cont"> <label class="filter" for="images">Додати фотографію</label> <input type="file" id="images" name="images" accept="image/*" onchange="checkFileCount(this)" multiple required> </div> <div class="image-preview"></div> <button type="submit" name="sumbit" class="sumbit-form">Опублікувати оголошення</button> </form> </div> </div> </body> </html>

/*Обнуление*/  *, // Половину стилей пришлось удалить из-за ограничения по объему, но вроде все важные есть  *:before,  *:after{     padding: 0;     margin: 0;     border: 0;     box-sizing: border-box;  } .image-preview {     display: flex; } .image-preview img {     width: 100px;     height: 100px;     object-fit: cover; /* чтобы изображение не растягивалось и не сжималось, сохраняя соотношение сторон */     margin: 5px; }  .remove-button {     margin-left: -20px;     height: 15px;     width: 15px;     margin-top: 5px;     display: block;     color: red; } .remove-button:hover {     cursor: pointer;     background-color: pink; } .filters {     background-color: #788AB2;     padding: 10px 20px;     width: 590px;     height: 10%;     box-sizing: border-box;     font-size: 20px;     font-family: Tahoma;     color: white;     display: flex;     flex-direction: column; } .filters label, .filters select, .filters option {     flex: 1;     display: inline-block;     margin-bottom: 12px;     line-height: 26px; } .filters label {      margin-top: 12px } .filters p{     align-self: center;     justify-self: center;     font-size: 24px;     margin-bottom: 10px; } .cont {     display: flex;     align-items: center;     justify-content: space-between; } .filters select {     position: relative;     display: block;     flex: 3.1;     margin: 5px 0;     font-family: 'Open Sans', 'Helvetica Neue', 'Segoe UI', 'Calibri', 'Arial', sans-serif;     font-size: 18px;     color: #60666d;     flex-basis: 50px; } .center-global-container{     display: flex;     justify-content: center;     align-items: center;     flex-direction: column; } .addForm-container {     width: 32.5%;     min-width: 325px;     display: flex;     flex-direction: column; } .addForm {     width: 100%;     display: flex;     flex-direction: column; } .errorMessage{     margin-top: 0px;     margin-bottom: 10px;     font-size: 1.25rem;     color: red; }

/*Обнуление*/ *, // Половину стилей пришлось удалить из-за ограничения по объему, но вроде все важные есть *:before, *:after{ padding: 0; margin: 0; border: 0; box-sizing: border-box; } .image-preview { display: flex; } .image-preview img { width: 100px; height: 100px; object-fit: cover; /* чтобы изображение не растягивалось и не сжималось, сохраняя соотношение сторон */ margin: 5px; } .remove-button { margin-left: -20px; height: 15px; width: 15px; margin-top: 5px; display: block; color: red; } .remove-button:hover { cursor: pointer; background-color: pink; } .filters { background-color: #788AB2; padding: 10px 20px; width: 590px; height: 10%; box-sizing: border-box; font-size: 20px; font-family: Tahoma; color: white; display: flex; flex-direction: column; } .filters label, .filters select, .filters option { flex: 1; display: inline-block; margin-bottom: 12px; line-height: 26px; } .filters label { margin-top: 12px } .filters p{ align-self: center; justify-self: center; font-size: 24px; margin-bottom: 10px; } .cont { display: flex; align-items: center; justify-content: space-between; } .filters select { position: relative; display: block; flex: 3.1; margin: 5px 0; font-family: 'Open Sans', 'Helvetica Neue', 'Segoe UI', 'Calibri', 'Arial', sans-serif; font-size: 18px; color: #60666d; flex-basis: 50px; } .center-global-container{ display: flex; justify-content: center; align-items: center; flex-direction: column; } .addForm-container { width: 32.5%; min-width: 325px; display: flex; flex-direction: column; } .addForm { width: 100%; display: flex; flex-direction: column; } .errorMessage{ margin-top: 0px; margin-bottom: 10px; font-size: 1.25rem; color: red; }

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Кирилл JS Ответ

Для реализации поочередной загрузки изображений, их предпросмотра и возможности удаления по кнопке вам понадобится использовать HTML, CSS и JavaScript, а также серверный язык программирования, например PHP, для обработки загруженных изображений.

Вот пример кода, демонстрирующий данную функциональность:

```html

Загрузка изображений

#images-preview {
display: flex;
flex-wrap: wrap;
}
.image-preview {
margin: 10px;
}

const imageInput = document.getElementById('image-input');
const deleteButton = document.getElementById('delete-button');
const imagesPreview = document.getElementById('images-preview');

imageInput.addEventListener('change', function() {
const files = imageInput.files;

for(let i = 0; i < files.length; i++) {
const file = files[i];
const reader = new FileReader();

reader.onload = function(e) {
const imagePreview = document.createElement('img');
imagePreview.src = e.target.result;
imagePreview.className = 'image-preview';
imagesPreview.appendChild(imagePreview);
}

reader.readAsDataURL(file);
}
});

deleteButton.addEventListener('click', function() {
const imagePreviews = document.getElementsByClassName('image-preview');

while(imagePreviews[0]) {
imagePreviews[0].parentNode.removeChild(imagePreviews[0]);
}
});

```

Этот код позволяет загружать изображения, предпросматривать их на странице и удалять их по кнопке. При выборе изображений через input file они поочередно отображаются на странице в виде миниатюр, которые можно удалить, нажав на кнопку "Удалить".

Помимо фронтенд-части, вам также потребуется написать серверный код на PHP для обработки загруженных изображений и их сохранения на сервере. В этом случае после выбора изображений пользователем, вы можете отправить их на сервер с помощью AJAX запроса и сохранить их на сервере.

Надеюсь, данное решение поможет вам реализовать функциональность поочередной загрузки изображений с их предпросмотром и возможностью удаления.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно