Те, кто использует HTML5 Canvas знают, что картинку нельзя использовать через URL к ней. Картинку нужно сначала загрузить либо через тэг img, либо через объект Image, либо через data: url.
Чтобы не думать о загрузке каждой картинки, делают загрузку всех необходимых картинок перед отрисовкой самой сцены. В этом топике я приведу в пример свой загрузчик изображений, который использует Mootools с его механизмов для работы с классами.
Как должен выглядеть такой класс с точки зрения проектирования? Он должен принимать адреса изображений, которые должны загрузиться, и каким-то образом, оповещать о процессе загрузки.
К счастью, Mootools предоставляет некоторые средства для удобной работы с событиями.
В классе реализуются обработчики событий onload, onerror, onabort объектов Image, и, когда процент общей загрузки изменился, генерируются свои.
Класс генерирует три события:
Пример использования:
В качестве представления прогресса я написал еще один класс, который через Canvas рисует прогрессбар.
Пример реализации можно посмотреть здесь ( грузит где-то 100кбайт Гугловских логотипов )
P.S. Я планирую написать цикл статьей про игростроительство через Html5 Canvas. Это первая, хоть она и немного банальная. В следующей статьей я постараюсь описать принцип построения ландшафта в изометрической проекции ( по тайлам ).
Чтобы не думать о загрузке каждой картинки, делают загрузку всех необходимых картинок перед отрисовкой самой сцены. В этом топике я приведу в пример свой загрузчик изображений, который использует Mootools с его механизмов для работы с классами.
Как должен выглядеть такой класс с точки зрения проектирования? Он должен принимать адреса изображений, которые должны загрузиться, и каким-то образом, оповещать о процессе загрузки.
К счастью, Mootools предоставляет некоторые средства для удобной работы с событиями.
В классе реализуются обработчики событий onload, onerror, onabort объектов Image, и, когда процент общей загрузки изменился, генерируются свои.
Класс генерирует три события:
- onStart(): вызывается на старте загрузки;
- onUpdate( percent ): вызывается, когда процент загрузки изменился;
- onComplete(): вызывается, когда все изображения загрузились.
var Imageloader = new Class({
//Наследуем интерфейсы Options и Events
Implements : [Options, Events],
options : {
//Описания событий
//загрузка началась
onStart : $empty,
//обновился процент загрузки
onUpdate : $empty,
//загрузка завершилась
onComplete : $empty,
//Массив хешей изображений. Хеш вида
//{
// "url" : url,
// "key" : key,
// "size" : size
//}
images : []
},
initialize : function(options) {
this.setOptions(options);
//В этом хеше будут храниться загруженные картинки
this.images = {};
//Объявляем начальные переменные
this.totalCount = this.options.images.length;
this.successCount = this.failureCount = this.loadedCount = 0;
this.successSize = this.failureSize = this.loadedSize = this.totalSize = 0;
this.progress = 0;
},
start : function() {
//Создаем объекты Image,
//добавляем слушатели
$each(this.options.images, function(obj) {
this.totalSize += obj.size;
var image = new Image();
image.onload = this.onComplete.bind(this,obj);
image.onerror = this.onFailure.bind(this,obj);
image.onabort = this.onFailure.bind(this,obj);
image.src = obj.url;
this.images[obj.key] = image;
}.bind(this));
this.fireEvent('start');
},
//Метод возвращает объект Image по ключу
getImage : function( key ) {
return this.images[key];
},
//изображение загрузилось
onComplete : function( image ) {
//Увеличиваем счетчики
this.successCount++;
this.successSize += image.size;
this.onImageEvent(image);
},
//изображение не загрузилось
onFailure : function( image ) {
//Увеличиваем счетчики
this.failureCount++;
this.failureSize += image.size;
//Вместо незагруженного изображения подставляем пустое
this.images[image.key] = new Image();
this.onImageEvent(image);
},
onImageEvent : function( image ) {
//Увеличиваем счетчики
this.loadedCount++;
this.loadedSize += image.size;
//Высчитываем общий прогресс
var progress = Math.round(this.loadedSize*100/this.totalSize);
if ( this.progress != progress ) {
this.progress = progress;
//Вызываем событие update
this.fireEvent('update',progress);
}
//Если все изображения загружены
if ( this.totalCount == this.loadedCount ) {
this.fireEvent('complete');
}
}
});
* This source code was highlighted with Source Code Highlighter.
Пример использования:
var il = new Imageloader({
onUpdate : function(percent) {
//Обновляем процент загрузки
alert(percent);
},
onComplete : function( ) {
//Можем успешно использовать загруженные изображения
alert("done");
alert(d.getImage("winter2010").complete);
},
//Хеш изображений
images : [{
'url' : 'http://www.google.com/intl/en_ALL/images/srpr/logo1w.png',
'key' : 'main_logo',
'size' : 7
},{
'url' : 'http://www.google.com/logos/winter2010_1-hp.jpg',
'key' : 'winter2010',
'size' : 32
},{
'url' : 'http://www.google.com/logos/komensky10_hp.gif',
'key' : 'komensky',
'size' : 26
}]
});
//Запускаем загрузку
il.start();
* This source code was highlighted with Source Code Highlighter.
В качестве представления прогресса я написал еще один класс, который через Canvas рисует прогрессбар.
Пример реализации можно посмотреть здесь ( грузит где-то 100кбайт Гугловских логотипов )
P.S. Я планирую написать цикл статьей про игростроительство через Html5 Canvas. Это первая, хоть она и немного банальная. В следующей статьей я постараюсь описать принцип построения ландшафта в изометрической проекции ( по тайлам ).