Как использовать javascript для отображения анимации загрузки до того, как API полностью загрузит данные?

Как заставить данные API сначала загрузить анимацию загрузки, прежде чем все данные будут возвращены, а затем открыть всплывающее окно после того, как API передаст все данные? Потому что в настоящее время, когда загрузка исчезает, данные во всплывающем окне не были полностью загружены, что приведет к тому, что пользователь увидит момент, когда данные будут загружены, и размер всплывающего окна изменится. Я надеюсь, что анимация загрузки будет отображаться до того, как все данные будут загружены во всплывающее окно. После загрузки данных откройте всплывающее окно и закройте анимацию загрузки. Как мне изменить это, чтобы улучшить мой пользовательский опыт? Спасибо

let btn = document.querySelector('.btn');
let popup = document.querySelector('.popup');
let wrap = document.querySelector('.wrap');
let photo = document.querySelector('.photo');
let svg = document.querySelector('svg');

btn.addEventListener('click', function(e) {
  svg.style.display = "block"

  axios.get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      let Data = response.data.message;
      photo.src = Data;
      svg.style.display = "none"
      popup.style.display = "flex";
    })
    .catch((error) => console.info(error));

});

wrap.addEventListener('click', function(e) {
  e.stopPropagation();
});

popup.addEventListener('click', function() {
  popup.style.display = "none";
});
.popup {
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
  height: 100vh;
  display: none;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.popup .wrap {
  width: 300px;
  background-color: #fff;
  text-align: center;
  border-radius: 20px;
  padding: 20px;
}

.popup .wrap .photo {
  width: 100%;
  height: 100%;
  object-fit: conver;
  border-radius: 20px;
}

svg {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

svg .load {
  stroke-dasharray: 0 500;
  animation: rot 1s linear infinite;
}

@keyframes rot {
  100% {
    stroke-dasharray: 500 500;
  }
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js"></script>
<button class='btn'>open data</button>


<div class = "popup">
  <div class = "wrap">
    <h1>Pet</h1>
    <img class = "photo" src = "" alt = "">
  </div>
</div>

<svg width = "240px" height = "240px" version = "1.1" xmlns = "http://www.w3.org/2000/svg">
        <circle cx = "110" cy = "110" r = "90" stroke-width = "10" stroke = "gainsboro" fill = "none"></circle>
        <circle cx = "110" cy = "110" r = "90" stroke-width = "10" stroke = "darkturquoise" fill = "none" class = "load"></circle>
    </svg>
css-tricks.com/…
The scion 05.02.2023 07:46
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

Вот изменение, которое вам нужно сделать:

btn.addEventListener('click', function(e) {
  svg.style.display = "block"

  axios.get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      // set handler to show the image once it is loaded
      photo.addEventListener('load', () => {
        svg.style.display = "none"
        popup.style.display = "flex";
      });
      // set image src after adding 'load' handler
      photo.src = response.data.message;
    })
    .catch((error) => console.info(error));

});

Обновление на основе дополнительных вопросов в комментариях

Для обработки нескольких изображений вам понадобится немного более сложный подход. Поскольку ваш код был просто примером для одного изображения, для простоты и демонстрации, основываясь на вашем вопросе в комментариях, я предполагаю, что ваш сервер может возвращать массив URL-адресов изображений.

  btn.addEventListener('click', function(e) {
  svg.style.display = "block"

  axios.get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      // assuming your API returns tens of images
      // this is an array of image URLs
      const imageURLs = response.message.imageURLs;
      // retrieving array of img elements from the page
      // I would recommend actually generating img tags here
      const imageElements = document.querySelector('.photo');
      // we create a Promise for each img element
      const imagePromises = imageElements.map((element, index) => {
        return new Promise((resolve, reject) => {
         element.addEventHandler('load', resolve);
         element.addEventHandler('error', (e) => reject(e));
         element.src = imageURLs[index];
       });
      });
      // this will wait for all the promises to settle
      Promise.allSettled(imagePromises).then((results) => {
        // go through 'results' and handle errors if needed
        // otherwise, this is the place where you know that
        // all the images are loaded/failed
        svg.style.display = "none"
        popup.style.display = "flex";
      });
    })
    .catch((error) => console.info(error));
});

Что касается того, что вы должны делать в catch, это во многом зависит от поведения и визуальной обратной связи, которую вы должны сделать в случае ошибок. Если вы хотите уведомить пользователя об ошибке, вы можете использовать функцию catch, например, для отображения какого-либо всплывающего окна.

Пожалуйста, дайте мне знать, если это поможет.

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

WEI A 05.02.2023 08:20

Также задайте вопрос, потому что я не знаком с использованием javaScript, хотел бы спросить! Какую информацию обычно следует помещать в улов? Насколько я понимаю, это просто возвращает сообщение об ошибке. Если сегодня нет необходимости возвращать пользователю сообщение об ошибке, то обычно не нужно ничего писать в catch?

WEI A 05.02.2023 08:21

@WEIA Я обновил ответ, добавив обработку нескольких изображений. Дайте мне знать, если у вас возникнут дополнительные вопросы.

RAllen 05.02.2023 10:41

Чтобы решить эту проблему, вы можете попробовать добавить свойство onload к переменной photo. Событие onload происходит, когда объект загружен. Ссылка: https://www.w3schools.com/jsref/event_onload.asp

let btn = document.querySelector('.btn');
let popup = document.querySelector('.popup');
let wrap = document.querySelector('.wrap');
let photo = document.querySelector('.photo');
let svg = document.querySelector('svg');

btn.addEventListener('click', function(e) {
  svg.style.display = "block"

  axios.get("https://dog.ceo/api/breeds/image/random")
    .then((response) => {
      let Data = response.data.message;
      photo.src = Data;
      photo.onload = () => {
        svg.style.display = "none";
        popup.style.display = "flex";
      }
    })
    .catch((error) => console.info(error));

});

wrap.addEventListener('click', function(e) {
  e.stopPropagation();
});

popup.addEventListener('click', function() {
  popup.style.display = "none";
});
.popup {
  background-color: rgba(0, 0, 0, 0.5);
  width: 100%;
  height: 100vh;
  display: none;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.popup .wrap {
  width: 300px;
  background-color: #fff;
  text-align: center;
  border-radius: 20px;
  padding: 20px;
}

.popup .wrap .photo {
  width: 100%;
  height: 100%;
  object-fit: conver;
  border-radius: 20px;
}

svg {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

svg .load {
  stroke-dasharray: 0 500;
  animation: rot 1s linear infinite;
}

@keyframes rot {
  100% {
    stroke-dasharray: 500 500;
  }
}
<script src = "https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js"></script>
<button class='btn'>open data</button>


<div class = "popup">
  <div class = "wrap">
    <h1>Pet</h1>
    <img class = "photo" src = "" alt = "">
  </div>
</div>

<svg width = "240px" height = "240px" version = "1.1" xmlns = "http://www.w3.org/2000/svg">
        <circle cx = "110" cy = "110" r = "90" stroke-width = "10" stroke = "gainsboro" fill = "none"></circle>
        <circle cx = "110" cy = "110" r = "90" stroke-width = "10" stroke = "darkturquoise" fill = "none" class = "load"></circle>
    </svg>

Другие вопросы по теме