Reputation:
background-image:url('images/bg1.png'), url('images/speed/bg1.jpg');
I'm trying to take advantage of the option for multiple background images for an element to load, first, a fast, low-res version of each background image to be replaced by the higher quality version once it has loaded.
Any efficient solutions?
Note: The below is more wishful thinking than an actual question; I thought this might be a good topic to pin the inquiry to.
As a side question, does anyone know of a method of using this sort of idea, instead have the image transition into rendering from low-to high res, with some sort of noise effect, if you see where I'm going with that. Would be as if each image sort of smoothed out from plain noise to HD, gaining resolution until it hits the proper level, as it loads.
I guess what I'm getting at is: "can a script be written to load a single image as variable noise slowly gaining clarity as the image loads, instead on loading 100% res from the top-down?"
Upvotes: 11
Views: 8807
Reputation: 982
//
// here's more elaborate, and user friendly, version
// works the same as previous,
// I've just added the possibility to subscribe funcions
// for load/error/abort/done events separately,
// and pass images as image array with the hash map of options to the funcion,
// and some cleanup code to remove unnecesary function handlers
// after download is done.
//
// use:
//
// cacheimages(
// {
// imgs : [
// 'http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Flag_of_the_United_Nations.svg/2000px-Flag_of_the_United_Nations.svg.png',
// 'http://upload.wikimedia.org/wikipedia/commons/e/e5/IBM_Port-A-Punch.jpg',
// 'http://upload.wikimedia.org/wikipedia/commons/7/7e/Tim_Berners-Lee_CP_2.jpg',
// 'http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/NewTux.svg/2000px-NewTux.svg.png',
// 'http://upload.wikimedia.org/wikipedia/commons/4/4c/Beekeeper_keeping_bees.jpg',
// 'http://upload.wikimedia.org/wikipedia/commons/9/9a/100607-F-1234S-004.jpg'
// ],
//
// load : function () { console.log( arguments, this ); },
// # triggered when single image is sucessfuly cached
// # @param1, ( string ), loaded image source path
// # @param2, ( event object ), native event object generated
// # context ( this ), Image object, target obj related with event
//
// error : function () { console.log( arguments, this ); },
// # triggered when error occured when tring to download image
// # @param1, ( string ), path to the image failed to load
// # @param2, ( event object ), native event object describing the circumstance
// # context ( this ), Image object, target obj related with event
//
// abort : function () { console.log( arguments, this ); },
// # triggered when download is haulted by user action ( browsers 'stop' button )
// # @param1, ( string ), path to the image failed to load
// # @param2, ( event object ), native event object generated
// # context ( this ), Image object, target obj related with event
//
// done : function () { console.log( arguments, this ); }
// # triggered after download proccess completes
// # @params, ( string(s) ), images in question
// # context ( this ), document
// }
// );
//
;(( function ( methodName, dfn ) {
// add "cacheimages" function identifier to target context ( window )
this[methodName] = dfn();
} ).call(
self,
"cacheimages",
function () {
var emptyfn = function () {};
var isfn = function ( o ) {
return typeof o === "function";
};
var isplainobj = function ( o ) {
return Object.prototype.toString.call( o ) === "[object Object]";
};
var isarray = function ( o ) {
return Object.prototype.toString.call( o ) === "[object Array]";
};
var defaults = {
load : emptyfn,
error : emptyfn,
abort : emptyfn,
done : emptyfn
};
var imgreg = /\.(?:jpe?g|jpe|png|gif|bmp|tiff?|tga|iff)$/i;
var events = ["onload", ,"onerror" ,"onabort"];
var _F = function ( settup ) {
if (
isplainobj( settup )
&& (
isarray( settup.imgs )
&& ( settup.imgs.length > 0 )
)
) {
var pics = [];
var n = 0;
var opts = {
load : isfn( settup.load ) ? settup.load : defaults.load,
error : isfn( settup.error ) ? settup.error : defaults.error,
abort : isfn( settup.abort ) ? settup.abort : defaults.abort,
done : isfn( settup.done ) ? settup.done : defaults.done,
imgs : settup.imgs.filter(
function ( imgstr ) {
return imgreg.test( String( imgstr ) );
}
)
};
var loadhandler;
if (
opts.imgs.length == 0
) {
opts.done.call( document );
return [];
}
loadhandler = function ( e ) {
e || ( e = window.event );
n += 1;
if ( n < opts.imgs.length ) {
opts[ e.type ].call( this, this.src, e );
// console && console.log( e.type, ' --> [ ', this.src, ' ].' );
} else {
opts.done.apply( document, opts.imgs );
pics.forEach(
function ( imgobj ) {
events.forEach(
function ( vnt ) {
imgobj[vnt] = null;
}
);
}
);
}
};
opts.imgs.forEach(
function ( imgstr, i ) {
pics[i] = new Image;
events.forEach(
function ( vnt ) {
pics[i][vnt] = loadhandler;
}
);
pics[i].src = imgstr;
}
);
return opts.imgs.concat();
} else {
return false;
}
};
return _F;
}
));
//
Upvotes: 1
Reputation: 982
//
// You have dozen of hd photos, and don't want to embed them right from the get go
// in order to avoid 'interlaced' load, boost application load, etc.
// Idea is to place lo-res photos, temporarily, in place where hd ones should go,
// while downloading full quality images in the background.
//
// People usualy do this kind of caching by attaching 'onload' event handler to off-screen
// Image object ( created by new Image(), document.createElement('img'), or any
// other fashion ), which gets executed natively by a browser when the event
// ( 'onload' in this case ) occurs, and setting the '.src' property of an image to
// the phisical path ( relative/absolute ) of an img to start the download process.
// The script pressented here use that approach for multiple images,
// and notifies of task done by running provided function.
//
// So, solution is to provide locations of images you want to,
// and get notified when they get fully downloaded, and cached by browser.
// To do that you pass a function as 1st parameter to the fn below,
// passing as many images as needed after it.
//
// Code will scan through provided images keeping the ones that are actualy
// image files( .jpeg, .png, .tiff, etc.), create 'off-screen' Image objects
// and attach onload/onerror/onabort handler fn to each one( which will be called
// when coresponding circumstance occurs ), and initiate loading by setting the
// .src property of an Image object.
//
// After the 'load-handler' has been called the number of times that coresponds to
// number of images ( meaning the dload process is done ), script notifies you
// of job done by running the function you provided as first argument to it,
// additinaly passing images( that are cached and ready to go ) as
// parameters to callback fn you supplied.
//
// Inside the callback you do whatever you do with cached photos.
//
function hd_pics_dload( fn /* ,...hd-s */ ) {
var
n = 0, // this one is used as counter/flag to signal the download end
P = [], // array to hold Image objects
// here goes the image filtering stuff part,
// all the images that pass the 'regex' test
// ( the ones that have valid image extension )
// are considerd valid, and are kept for download
arg_imgs = Array.prototype.filter.call(
Array.prototype.slice.call( arguments, 1 ),
function ( imgstr ) {
return ( /\.(?:jpe?g|jpe|png|gif|bmp|tiff?|tga|iff)$/i ).test( imgstr );
}
);
// aborts script if no images are provided
// runs passed function anyway
if ( arg_imgs.length === 0 ) {
fn.apply( document, arg_imgs );
return arg_imgs;
}
// this part keeps track of number of 'load-handler' calls,
// when 'n' hits the amount of given photos
// provided callback is runned ( signaling load complete )
// and whatever code is inside of it, it is executed.
// it passes images as parameters to callback,
// and sets it's context ( this ) to document object
var hd_imgs_load_handler = function ( e ) {
// logs the progress to the console
console.log( e.type, ' -- > ', this.src );
( ++n === arg_imgs.length )
&& fn.apply( document, arg_imgs );
};
// this part loops through given images,
// populates the P[] with Image objects,
// attaches 'hd_imgs_load_handler' event handler to each one,
// and starts up the download thing( by setting '.src' to coresponding image path )
for (
var i = 0,
len = arg_imgs.length;
i < len;
i++
) {
P[i] = new Image;
P[i].onabort = hd_imgs_load_handler;
P[i].onerror = hd_imgs_load_handler;
P[i].onload = hd_imgs_load_handler;
P[i].src = arg_imgs[i];
}
// it gives back images that are about to be loaded
return arg_imgs;
}
//
// use:
hd_pics_dload(
// 1st provide a function that will handle photos once cached
function () { console.log('done -> ', arguments ); },
// and provide pics, as many as needed, here
// don't forget to separate all parameters with a comma
'http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Flag_of_the_United_Nations.svg/2000px-Flag_of_the_United_Nations.svg.png',
'http://upload.wikimedia.org/wikipedia/commons/e/e5/IBM_Port-A-Punch.jpg',
'http://upload.wikimedia.org/wikipedia/commons/7/7e/Tim_Berners-Lee_CP_2.jpg',
'http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/NewTux.svg/2000px-NewTux.svg.png',
'http://upload.wikimedia.org/wikipedia/commons/4/4c/Beekeeper_keeping_bees.jpg',
'http://upload.wikimedia.org/wikipedia/commons/9/9a/100607-F-1234S-004.jpg'
);
//
Upvotes: 6
Reputation: 761
Instead
- set the width and height using default either paint or Photoshop
- smush the image using http://www.smushit.com/ysmush.it/
Setting image width & height via html tags & CSS can cause the image to render slowly.
Smushing is a progressive tool by Yahoo! that removes excess data from the image without changing the quality.
These techniques improve the image rendering time. You can also follow your technique to further improve the image loading time.
Upvotes: 1