Skip to content

Commit

Permalink
Merge pull request #2 from tbrebant/master
Browse files Browse the repository at this point in the history
Safer image loading
  • Loading branch information
Brebant committed May 9, 2014
2 parents 80e8f57 + 01beacd commit b237a2b
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 41 deletions.
18 changes: 18 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Release history

## v0.2.2

- Safer image loading: images with a wrong or missing source get a placeholder image (when used
in a DOM context a missing image is not a big deal, but when trying to draw it on a canvas it crashes javascript)

## v0.2.1

- Switch to wizcorp/util

## v0.2.0

- Lowercase name

## v0.1.0

- First version
100 changes: 66 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,79 @@
image-preloader
==============

Preload your images with the ImagePreloader
image-preloader is an image preloader particularly designed to work with canvas.

### Usage example
# Overview

Basically, you provide an object with a list of urls and you get back another object where the urls have been replaced with the corresponding images, ready to be drawn somewhere.

Simple example:

```javascript
var imagePreloader = new ImagePreloader();
var urlList = {
whatever1: 'http://domain/path/to/image1.png',
whatever2: 'http://domain/path/to/image2.png',
whatever3: 'http://domain/path/to/image3.png',
whatever4: 'http://domain/path/to/image4.png',
whatever5: 'http://domain/path/to/image5.png',
whatever6: 'http://domain/path/to/image6.png'
var assets = {
sprite: 'http://domain.whatever.com/assets/sprite1.png',
background: 'http://domain.whatever.com/assets/bg.png',
button: 'http://domain.whatever.com/assets/btn.png'
};
imagePreloader.add(urlList);
imagePreloader.add(assets);
imagePreloader.on('finished', function (data) {
// the images are in data.images, matching the
// provided object structure, so you can simply do:
assets = data.images;
// and now you have image objects instead of strings, you can do for example:
whateverContext.drawImage(assets.sprite, 0, 0);
});
imagePreloader.start();
```

var stepCb = function (data) {
var loaded = data.loaded;
var error = data.error;
var total = data.total;
console.log('loadInProgress: ' + (loaded + error) + '/' + total);
};
# In depth

var finalCb = function (data) {
var loaded = data.loaded;
var error = data.error;
var total = data.total;
var images = data.images;
console.log('All (' + total + ') pictures have been processed. ' + loaded + ' have been loaded and ' + error + ' have not.');
if (images.whatever1) {
document.body.appendChild(images.whatever1);
}
};
## .start() parameters

imagePreloader.on('error', stepCb);
imagePreloader.on('loaded', stepCb);
imagePreloader.on('finished', finalCb);
You can provide completely optional parameters to the start method:

var notMandatory = {
ttl: 5000,
maxParallel: 3
}
imagePreloader.start(notMandatory);
- `ttl`: the maximum time you want to wait on one image before having the onerror triggered (ms). Default value is 3000ms.
- `maxParallel`: the maximum number of images you want to allow to be loaded in parallel (if you want to avoid something else to be blocked). Default value is 5.
- `placeholderImgData`: what data image you want for failed images. Default is an empty 1x1 transparent png.

Example:
```javascript
imagePreloader.start({
ttl: 10000,
maxParallel: 2,
placeholderImgData: 'data:image/png;base64,iVBORw0KGgo....'
});
```

## events

You can listen for:

### finished

Sent back object contains:

- `loaded`: number of images successfully loaded
- `error`: number of images where loading failed
- `errKeys`: array containing the list of keys who failed
- `images`: object, matching the original urls object structure, where strings have been replaced by images objects

### loaded

Called every-time a picture is successfully loaded, you can use it for progress bars. Sent back object contains:

- `currentKey`: which key have been loaded
- `loaded`: number of images successfully loaded so far
- `error`: number of failed images so far
- `total`: total number of images we are processing

### error

Called every-time a picture fails to load, you can use it for progress bars. Sent back object contains:

- `currentKey`: which key failed
- `loaded`: number of images successfully loaded so far
- `error`: number of failed images so far
- `total`: total number of images we are processing
- `errorMsg`: string error message
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "image-preloader",
"version": "0.2.1",
"version": "0.2.2",
"description": "An image pre-loader component",
"dependencies": {
"Wizcorp/eventemitter": "*",
Expand Down
28 changes: 22 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var EventEmitter = require('EventEmitter');

var defaultTtl = 3000;
var defaultMaxParallel = 5;
var emptyImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';

function ImagePreloader() {
this.urlList = {};
Expand All @@ -12,9 +13,11 @@ function ImagePreloader() {
this.loading = 0;
this.loaded = 0;
this.error = 0;
this.errKeys = [];

this.ttl = defaultTtl;
this.maxParallel = defaultMaxParallel;
this.placeholderImgData = emptyImg;
}

inherit(ImagePreloader, EventEmitter);
Expand Down Expand Up @@ -70,18 +73,19 @@ function loadNext() {
var toLoad = that._keyMap.length;
if (!processed) {
if (err) {
that.imgList[key] = null;
that.imgList[key].src = that.placeholderImgData;
that.error++;
that.emit('error', {loaded: that.loaded, error: that.error, total: toLoad, errorMsg: err});
that.errKeys.push(key);
that.emit('error', {loaded: that.loaded, error: that.error, total: toLoad, errorMsg: err, currentKey: key});
} else {
that.loaded++;
that.emit('loaded', {loaded: that.loaded, error: that.error, total: toLoad});
that.emit('loaded', {loaded: that.loaded, error: that.error, total: toLoad, currentKey: key});
}
that.loading--;
processed = true;
}
if (that.loaded + that.error === toLoad) {
that.emit('finished', {loaded: that.loaded, error: that.error, total: toLoad, images: that.imgList}, 'test OKKKKKK');
that.emit('finished', {loaded: that.loaded, error: that.error, errKeys: that.errKeys, total: toLoad, images: that.imgList});
} else {
loadNext.call(that);
}
Expand All @@ -92,7 +96,12 @@ function loadNext() {
img.addEventListener('abort', onError, false);
ttlTimeout = setTimeout(onTimeout, this.ttl);

img.src = url;
if (url) {
img.src = url;
} else {
onError();
}

loadNext.call(this);
}

Expand All @@ -119,12 +128,19 @@ ImagePreloader.prototype.start = function (options) {
this.maxParallel = defaultMaxParallel;
}

if (options.placeholderImgData !== undefined) {
this.placeholderImgData = options.placeholderImgData;
} else {
this.placeholderImgData = emptyImg;
}

this.imgList = {};
this._keyMap = Object.keys(this.urlList);

this.loading = 0;
this.loaded = 0;
this.error = 0;
this.errKeys = [];

loadNext.call(this);
};
};

0 comments on commit b237a2b

Please sign in to comment.