Для игры нужно подгрузить заранее в районе 12 изображений, причем эти изображения могут варьироваться от случая к случаю. То есть сейчас мне нужно подгрузить одни 12 изображений (SVG), а завтра нужно будет другие 12. Поэтому вариант помещения их в <div style="display: none;"><img...></div>
не подходит, ибо в этом случае придется постоянно грузить все изображения, а понадобятся мне из них всего 12. Поэтому было решено подгружать их средствами JavaScript перед началом игры. Для этого я реализовал небольшой класс "AssetsPreloader", который, пока что, имеет единственный метод "preload", который принимает массив из объектов вида {src: "ссылка", id: "id"}
и подгружает необходимые изображения путем простого создания экземпляра класса Image()
(нативный).
class AssetsPreloader {
static preload(arr) {
arr.map((a) => {
let img = new Image(); img.src = a.src; img.id = a.id;
(this.assets = this.assets || []).push(img);
});
}
}
Все подгруженные изображения в итоге попадают в статическое свойство assets
этого класса.
Следующим в коде идет отрисовка первого кадра игры, где эти изображения уже используются. И, в общем-то, проблема в том, что отрисовка не происходит. До нее выполнение кода доходит, это я проверял, и после нее код выполняется, но сами изображения не отрисовываются. Насколько я понимаю, происходит это потому, что изображения не успевают загрузиться (даже несмотря на то, что загрузка их происходит с диска). Однако, если запросить отрисовку первого кадра прямо из консоли браузера, то все работает как надо и кадр рисуется нормально.
Весь код в общем и целом выглядит примерно так:
class AssetsPreloader {
static preload(arr) {
arr.map((a) => {
let img = new Image(); img.src = a.src; img.id = a.id;
(this.assets = this.assets || []).push(img);
this.done = true;
});
}
}
AssetsPreloader.preload([
{src: "images/image.svg", id: "id_of_image"},
...
]);
// ...
GAME.field.draw();
В итоге, вопрос сводится к тому, как максимально правильно подгружать изображения (да и вообще различного рода файлы) так, чтобы, пока они не загрузились, код далше не выполнялся. Причем, возможно, на экране в этот момент будет какой-нибудь прогресс-бар (то есть полностью фризиться скрипт тоже не должен). Первым делом мне в голову пришло добавить весь остальной код в коллбэк к методу preload()
, но эта идея успехом не увенчалась.
Прошу помощи. Интересует не только как, но и как наиболее правильно (best-practice, все такое).
P.S. Файл скрипта подключен к странице с атрибутом defer
. При использовании, например, async
, отрисовка либо происходит, либо нет (отчего зависит - не могу сказать). А вешать в сам код обработчики проверки загрузки страницы, готовности DOM или что-то в этом роде не хочу.
Привожу кусок своего кода предзагрузки изображений. Принимает в качестве аргумента функцию handler которая выполнится когда все изображения загрузятся (или сообщат о сбое при попытки загрузки изображения). Специально привожу в неизменённом состоянии, точно работающем правильно. .preloader меняется с использованием jquery, если он не нужен, можно убрать. Остальное нативный javascript.
Slider3D.prototype.loadAllImages = function( handler ) {
var self = this;
var currentImageLoadedIndex = 0;
for ( var index = 0; index < self.settings.images.length; index++ ) {
self.data.images[index] = new Image();
self.data.images[index].onload = self.data.images[index].onerror = function(){
if ( ++currentImageLoadedIndex >= self.settings.images.length ) {
self.settings.element.find('.preloading').hide();
if ( typeof handler === 'function' ) handler();
} else {
self.settings.element.find('.preloading').css('width',((currentImageLoadedIndex/self.settings.images.length)*100) + '%');
}
};
self.data.images[index].src = self.settings.images[index];
}
};
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Ситуация такая: есть слайдер, в котором есть кнопка, после нажатия на нее должен скрываться блок с другим классом, который вне слайдераПомогите...
На десктопах всё отлично работает, но на сенсорных экранах нетПодключал так:
Я не могу понять, почему он выполняет сначала 1, потом 3, потом 2?