предзагрузка изображений через JS для последующего использования на Canvas
Помогите, пожалуйста, разобраться.В чем проблема? ` let imgArr = [];
function preloadImages(sources) {
let k = 0
for (let source of sources) {
let img = document.createElement("img");
img.src = source.src;
img.value = source.value;
imgArr.push(img);
};
k++;
}
let sources = [
{ src: 'images/3-3/image_part_001.jpg', value: 0 },
{ src: 'images/3-3/image_part_002.jpg', value: 1 },
{ src: 'images/3-3/image_part_003.jpg', value: 2 },
{ src: 'images/3-3/image_part_004.jpg', value: 3 },
{ src: 'images/3-3/image_part_005.jpg', value: 4 },
{ src: 'images/3-3/image_part_006.jpg', value: 5 },
{ src: 'images/3-3/image_part_007.jpg', value: 6 },
{ src: 'images/3-3/image_part_008.jpg', value: 7 },
{ src: 'images/3-3/image_part_009.jpg', value: 8 },
];
preloadImages(sources);`
далее идет функция отрисовки :
`function draw() {
ctx.clearRect(0, 0, width, height);
drawPlayingField();
addInactiveImages();
addActiveImages();
drawScoreField()
}
draw();
function addInactiveImages() {
let k = 0;
for (let i = 0; i < rightField.length; i++) {
let a = rightField[i];
if (!a.isActive) {
ctx.drawImage(imgArr[k], a.x, a.y, a.s, a.s);
a.value = imgArr[k].value;
}
k++;
}
}
function addActiveImages() {
let k = 0;
for (let i = 0; i < rightField.length; i++) {
let a = rightField[i];
if (a.isActive) {
ctx.drawImage(imgArr[k], a.x, a.y, a.s, a.s);
a.value = imgArr[k].value;
}
k++;
}
}`
она отрисовывает все, кроме картинок. на элементе canvas висят слушатели событий, в том числе и mouse move, который вызывает функцию перерисовки draw. при первом mouse move картинки появляется. но не сразу при загрузке страницы. Подскажите, пожалуйста, как это исправить?
Ответы (2 шт):
Когда вы добавляете на страницу тег img, прямо в этот же момент рисовать их на canvas не имеет смысла, так как они еще не загрузились и даже не посылали запрос серверу чтобы найти картинку, которая уже закешировалась в браузере.
Необходимо дожидаться события load, после него можно отрисовывать картинки на canvas.
Это бы могло выглядеть так:
async function loadAndDraw(images){
let loaded = await Promise.all(images.map(source =>
new Promise((resolve,reject)=>{
let img = document.createElement("img");
Object.assign(img, source);
img.onload = ()=> resolve(img);
img.onerror = (event)=> reject(event);
})
));
// ... рисование на canvas ...
}
Вот так тоже работает:
function preloadImages(sources, callback) {
let counter = 0;
function onLoad() {
counter++;
if (counter == sources.length) callback();
}
let k = 0
for (let source of sources) {
let img = document.createElement("img");
img.onload = img.onerror = onLoad;
img.src = source.src;
img.value = source.value;
imgArr.push(img);
}
k++;
}
let sources = [
{ src: 'images/3-3/image_part_001.jpg', value: 0 },
{ src: 'images/3-3/image_part_002.jpg', value: 1 },
{ src: 'images/3-3/image_part_003.jpg', value: 2 },
{ src: 'images/3-3/image_part_004.jpg', value: 3 },
{ src: 'images/3-3/image_part_005.jpg', value: 4 },
{ src: 'images/3-3/image_part_006.jpg', value: 5 },
{ src: 'images/3-3/image_part_007.jpg', value: 6 },
{ src: 'images/3-3/image_part_008.jpg', value: 7 },
{ src: 'images/3-3/image_part_009.jpg', value: 8 },
];
function testLoaded() {
let widthSum = 0;
for (let i = 0; i < sources.length; i++) {
let img = document.createElement('img');
img.src = sources[i];
}
draw();
}
preloadImages(sources, testLoaded);