Выполнить функцию после загрузки массива изображений - PullRequest
1 голос
/ 26 января 2020

Я выполняю скрипт после загрузки изображения заголовка страницы:

objImg = new Image(); 
objImg.src = '/images/header.jpg';
objImg.onload = function() {
   $('#myDiv').fadeIn(500);
}

Это прекрасно работает. Однако на одной из страниц мне нужно выполнить его после загрузки четырех изображений вместо одного. Есть ли способ изменить это, чтобы это был массив вместо одного изображения?

Ответы [ 3 ]

1 голос
/ 27 января 2020

Я бы использовал что-то вроде этого.

Используйте тот же подход в вашем вопросе.

Для массива изображений присвойте классу слово image-wait-for-load для тега img

Теперь определите, сколько изображений на странице вы ожидаете.

var waitImageCount = $('.image-wait-for-load').length;

Код для проверки загрузки всех изображений.

$(document /* or what ever */).on('load', '.image-wait-for-load', function() {
  waitImageCount--; // decrease the counter

  if(waitImageCount === 0) {
    // all images are loaded.
    // Do what ever you like
  }
}); 

Обратите внимание, что этот непроверенный код, но я надеюсь, что что-то подобное должно работать.

0 голосов
/ 27 января 2020

В приведенной ниже демонстрации используются функция async и ключевое слово await , поэтому Promise контролирует асинхронное взаимодействие между клиентом (вами) и тестовым сервером в данный момент времени. конечная точка (первый параметр) . Передается селектор (второй необязательный параметр) элемента DOM, чтобы указать, где следует отображать изображения (по умолчанию "body", если не определено).

fetchImages("https://sub.domain.tld/path/to/json", "tagName#id.className[attribute]"/*or "body"*/)

fetch() - это асинхронная функция, которая гарантирует ответ или отклонение запрошенных данных через ключевое слово await. Метод .json() (также предшествующий await) извлекает JSON.

const response = await fetch(`https://api.myjson.com/bins/19fk22`);
let imgArray = await response.json();
/* At this point the JSON is stored in a variable called imgArray
imgArray = [
  "https://i.ibb.co/hZj77BZ/lena01.jpg",
  "https://i.ibb.co/7XxsBr5/lena02.png",
  "https://i.ibb.co/X7SCb3w/lena03.png"
]
*/

Далее, массив JSON (он же imgArray) проходит через метод массива .forEach((src, idx) => {.... Каждый URL (src первый параметр) в пределах imgArray обрабатывается. Ниже приведена пошаговая разбивка первого URL обрабатываемого изображения ( Обратите внимание, как второй параметр idx используется на шаге # 3 ):

  1. Ссылка на элемент DOM, в который изображения будут помещены в

    const node = document.querySelector('.gallery')
    // <header class="gallery">|<= images will be inserted here =>|</header>
    
  2. Извлеките имя файла изображения с помощью .split()

     let name = src.split('/')
     // ['https:', 'i.ibb.co', 'hZj77BZ', 'lena01.jpg']
     .pop()
     // 'lena01.jpg'
     .split('.')
     // ['lena01', 'jpg']
     .shift();
     // 'lena01'
    
  3. Назначить шаблонный литерал для htmlString переменной (let html) и затем интерполировать ${values} и / или ${expressions}

     let html = `
    <figure style="animation: ${3 * (idx+1)}s fadeIn">`
    /* <figure style="animation: 3s fadeIn">
    Each iteration is assigned an increased CSS animation-duration value.
    The first image fades in for 3sec, the second image fades in for 6sec, third 9sec, etc.
    The actual code for the animation is in the CSS.
    */
      `<img src="${src}">`
      // <img src="https://i.ibb.co/hZj77BZ/lena01.jpg">
      `<figcaption>${name}</figcaption>`
      /* <figcaption>LENA01</figcaption>
      The name value from step #2 is inserted as a caption and styled by CSS
      */ 
    `</figure>`;
    node.insertAdjacentHTML("beforeend", html);
    /* .insertAdjacentHTML(position, htmlString) is .innerHTML on steroids
    @Param: [Position]: "beforebegin", "afterbegin", "beforeend", or "afterend"
    @Param: [htmlString]: strongly suggest that template literals be used instead of literal strings
    

Демо

const endpoint = `https://api.myjson.com/bins/19fk22`;

const fetchImages = async(endpoint, selector = "body") => {
  const response = await fetch(endpoint);
  let imgArray = await response.json();
  imgArray.forEach((src, idx) => {
    const node = document.querySelector(selector);
    let name = src.split('/').pop().split('.').shift();
    let html = `
    <figure style="animation: ${3 * (idx+1)}s fadeIn">
      <img src="${src}">
      <figcaption>${name}</figcaption>
    </figure>`;
    node.insertAdjacentHTML("beforeend", html);
  });
}

fetchImages(endpoint, '.gallery');
.gallery {
  display: flex;
  justify-content: center;
  width: 96%;
  margin: 10px auto;
  padding: 5px;
  background: rgb(138, 56, 201);
}

figure {
  width: 50vw;
  margin: 10px 2.5px 5px;
}

figcaption {
  font: 700 small-caps 3vw/1 Arial;
  color: gold;
  text-align: center;
}

img {
  width: 100%;
  height: auto;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  50% {
    opacity: 0.66;
  }
  to {
    opacity: 1;
  }
}
<header class='gallery'></header>
0 голосов
/ 27 января 2020

Это можно сделать с помощью обещаний, таких как здесь . Или просто l oop при сохранении их источников в параллельном массиве и использовании функции обратного вызова, когда все изображения предварительно загружены. Параллельный массив также может быть полезен при ошибках загрузки, поэтому мы можем использовать его для отображения только предварительно загруженных и допустимых изображений.

Более сложный подход добавил бы функцию для проверки доступности изображения перед его предварительной загрузкой с использованием XMLHttpRequest (). ; или ajax.

Обратите внимание, что я использую здесь поддельную картинку для проверки сбоя загрузки.

var pix = new Array('https://image.shutterstock.com/image-photo/colorful-hot-air-balloons-flying-260nw-1033306540.jpg','https://images.fineartamerica.com/images-medium-large-5/hot-air-balloons-over-hay-bales-sunset-landscape-matthew-gibson.jpg','https://iso.500px.com/wp-content/uploads/2014/07/big-one.jpg','https://some.thing/undefined.jpg','https://cdn-media.rtl.fr/cache/4gx11M-ZCLtBdzqGMR2TWA/880v587-0/online/image/2019/1212/7799676803_l-enfant-de-the-mandalorian-est-la-star-de-la-galaxie.jpg');
 var total = pix.length;
 var ctr = 0;
 var cache=[];
 

for(var i=0; i<total; i++){
    var img = new Image();
    img.src = pix[i];    
    //We push it to the cached elements list
    cache.push(img);
    img.onload = function(){
        
        console.log('Pic loaded!');
        ctr++;
        //When all are loaded
        if(ctr == total){
            console.log('All done ;) ');
            //We append them to the targeted div 
            WellDone();
        }
    }
    img.onerror = function(){
        //Because we didn't test the picture loading before adding it, we have to remove the failing image from the array
        cache.splice(i, 1);
        ctr++;
        if(ctr == total){
            console.log('All done ;) ');
            //We append them to the targeted div 
            WellDone();
        }        
    }

}

function WellDone(){
    //finally here things could run in a sequence!
    for (var i = 0; i < cache.length; i++) {
    $('#myDiv').append(cache[i]);
    }
    
    cache=[];
$('#myDiv').fadeIn(500);
}
#myDiv{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="myDiv"></div>
...