JavaScript: Preloading images function - Usage, DOM ready & SEO? - javascript

With the help of Google I've written a small preloader script:
var i = 0;
function preloader() {
imageObj = new Image();
images = [
'some/image1.jpg',
'some/image2.jpg',
'some/image3.png',
'and.png',
'so.jpg',
'on.png'
];
for (i = 0; i <= 20; i ++) {
imageObj.src = images[i];
}
}
This function must be called in the head of my HTML file for maximum effect, right? Do I really need to declare var i = 0;? How can I fire another function once the preloading is complete?
Also, I would like to ask how to implement this function in running websites. Let's say I have a page that has 100 img tags. I guess I have to copy and paste the source into the images array by hand, right? Because to do that with a loop, the DOM needs to be ready which again means that the images have already started loading?
Does preloading affect SEO?
If there is a better jQuery way of preloading I would be ok with that.

Because you're assigning the image SRC to the same variable, the each new request will cancel the previous because it has not completed loading.
You can use an array for this as well:
imageObj = [];
...your code...
for (i = 0; i < images.length; i ++) {
imageObj[i] = new Image()
imageObj[i].src = images[i];
}
No, this will not affect SEO because the scrapers are looking at the TEXT of your page, not the images. You can run this before the DOM is ready because you're not manipulating the DOM - all images are in memory.
jQuery is simply made of JavaScript and does not really have anything that would speed the efficiency of this simple block of code.

Related

JavaScript, set same image source to different images (preload)

Sorry, maybe not correct title..
I have the next question: I want to make preloading with progress bar. And I stuck on one problem.
[CODE 1]:
//Preloader code
var img = [];
img[0] = new Image();
img[0].src = 'test0.jpg';
img[0].onload = function(){
//some code
}
//.....
img[100] = new Image();
img[100].src = 'test100.jpg';
img[100].onload = function(){
//some code
}
//.....
// all images loaded
//.....
/*
for expample in this part of code I need put my image 'test0.jpg' into html
*/
var temp_img = new Image();
temp_img.src = 'test0.jpg';
The question is : will it download 'test0.jpg' again or just take it from cache?
or better to do like this [CODE 2]:
//Preloader code
var img = [];
img['test0'] = new Image();
img['test0'].src = 'test0.jpg';
img['test0'].onload = function(){
//some code
}
//.....
img['test100'] = new Image();
img['test100'].src = 'test100.jpg';
img['test100'].onload = function(){
//some code
}
//.....
// all images loaded
//.....
/*
for expample in this part of code I need put my image 'test0.jpg' into html
*/
var temp_img = img['test0'];
// draw temp_img
I want to use CODE 1. But will it slow down my app? Or better to use CODE 2? Thanks in advance.
Both methods have benefits and drawbacks.
The first method is much lighter on image elements and as a general rule, the fewer DOM elements you generate, the better. There is a chance, though, that the browser will not serve the image from the cache depending on how much information is being loaded. Worst case, you will need to fetch from the network again if the browser has removed the image from the cache.
The second method is much safer and will keep the image held in memory, meaning even if the browser doesn't cache it, it's still available. It's heavier on image elements, though.
Which solution is better depends on your situation. If you're not loading a large amount of images, I'd say solution 1 is the better choice as it leverages the browser's cache. If you really can't afford to reload images off the network, though, solution 2 is safer.
TL;DR
Solution 1 shouldn't slow down your application, but solution 2 will ensure you don't fetch from the network again.
With code 1, your preloader would be useless right? I'd go with 2

what is best to use canvas or img for frequent updates?

I have a javascript timer.
It refreshes the img src on a 200ms interval.
I have taken a look at the canvas object. I am unsure whether it is recommended to use the canvas instead of the img element?
I am running tests on both and cannot see any differences in performance.
This is my code for using the timer/img:
This is my code:
var timer4x4
var cache4x4 = new Image();
var alias = 'test';
var lastUpdate = 0;
function setImageSrc4x4(src) {
live4x4.src = src;
timer4x4 = window.setTimeout(swapImages4x4, 200);
}
function swapImages4x4() {
cache4x4.onload = function () {
setImageSrc4x4(cache4x4.src);
};
cache4x4.onerror = function () {
setImageSrc4x4("http://127.0.0.1/images/ERROR.jpg");
};
cache4x4.src = null;
cache4x4.src = 'http://127.0.0.1/Cloud/LiveXP.ashx?id=' + createGuid() + '&Alias=' + alias + '&ReSync=' + reSync;
reSync = 0;
}
*nb will add canvas code in a bit
I am streaming images from my client desktop PC to my web server. I am trying to display as many images (FPS) as possible. The image is a container for 4 smaller images. Stitched up on the client and sent to the server.
I have Googled and it says if doing pixel manipulation and aniumation use canvas.
But, I am just doing animation.
Thanks
The canvas element was designed to draw / edit / interact with images in it. If all you do is display the image, then you don't need that and a simple img is the semantically correct choice (with the added bonus of being compatible on more devices).
In both cases, the performance will be similar (if not the same) because the only thing to happen is that the image is downloaded.
While performance-wise you won't notice much of a difference, since you still cannot fully rely on HTML5 support yet, it is probably best to go with the img-solution for now.

Check if Images are loaded before gameloop

So far my program is working the way I want it to. This works fine:
// Player object
var player = {
x: 10,
y: 10,
draw: function () {
ctx.drawImage(playerImg, 0, 0);
...
Should I check if playerImg is loaded first, even though it works correctly so far?
Also, what is the best way to check. I was thinking about putting all the images in an array. Then check with the onLoad function. If they are all loaded then I will start the game loop. Is this a good idea?
Thanks
How image loading works
You need to check if the image is loaded as image loading is asynchronous. You may experience that your code works sometimes without. This is mainly because your image exists in the cache and the browser is able to load it fast enough before the drawImage is called, or the image exists on local disk.
However, new users will need to download the data first and you don't want first-time users to experience errors such as images not showing because they are not finished loading.
As it works asynchronous your code will continue to execute while the image loading takes place in the background. This may cause your code to execute before the image has finished loading. So handling image loading is important
Handling multiple images
You can load all your images first (or those you need to start with) and you can define them using array:
var imageURLs = [url1, url2, url3, ...],
images = [],
count = imageURLs.length;
Then iterate and create the image elements:
for(var i = 0; i < count; i++) {
/// create a new image element
var img = new Image();
/// element is valid so we can push that to stack
images.push(img);
/// set handler and url
img.onload = onloadHandler;
img.src = imageURLs[i];
/// if image is cached IE (surprise!) may not trigger onload
if (img.complete) onloadHandler().bind(img);
}
and in the callback function do the inventory count:
function onloadHandler() {
/// optionally: "this" contains current image just loaded
count--;
if (count === 0) callbackDone();
}
Your callback is the code you want to execute next. Your images will be in the array images in the same order as the imageURLs.
For production you should also incorporate an onerror handler in case something goes wrong.

Chrome / Firefox Cached Images Issue

I'm having trouble when preloading images and creating elements on the fly. The script loads a list of image URLs, creates canvas elements etc.
The problem is that on subsequent "soft" refreshes or submission of the same URL the preload loop isn't initiated, so the canvas elements etc. are not created. I'm pretty certain this has something to do with resource caching - however - why the script isn't iterating through the image URL list and building the DOM as expected I'm not sure... Here's an example
The JavaScript on the page is optimised output, but the preload loop looks like this:
// Images array
var images = [];
for (var i = 0; i < l.length; ++i) {
// Create canvas element
var canvas = document.createElement('canvas');
// Canvas element properties
canvas.width = l[i].w;
canvas.height = l[i].h;
canvas.style.display = 'none';
// Image element + mouse over event
images[i] = document.getElementById('i' + i).getElementsByTagName('img')[0];
images[i].addEventListener('mouseover', function() {
handleCanvas(this);
}, false);
// Push canvas into DOM
images[i].parentNode.insertBefore(canvas, images[i]);
// Preload item from processed images list
var image = new Image;
image.src = l[i].i;
}
I'd prefer not to resort to headers or "URL?random=37436464" type fixes if possible. Tested on nightly versions of Chrome and Firefox on Ubuntu 12.10.
After further investigation (testing in IE9) it appears the issue was cause by asynchronous loading of the JavaScript and lagging variable initiation.

Is there a way of "controlled" preloading of images (maybe with help of jQuery)?

For a sort of slideshow I'm trying to implement a clever image pre-loader, which should work as following:
On load of slideshow first image is shown and images start loading
in background in order 2, 3, 4, ...
If user decides to switch to image n (which can be done via
search or thumbs or ...) and the triggered preload (from 1.) didn't load n yet, the order (2, 3, 4, ...) established in 1. will be re-organized with n as first element.
Other possibility for 2. could be to suspend preloading, load image n, and continue preload, but I'd prefer first idea because this will give you the freedom of more sophisticated re-ordering, e.g. (n, n+1, n+2, ..., last, 1st-not-loaded, 2nd-not-loaded, ...).
So far I just did a simple preload-loop like that:
for (var i = 0; i < issue.pages.length; i++)
{
log("preloading image from URL " + issue.pages[i].imageUrl);
var img = new Image();
img.onload = function()
{
log("reading loading image " + this.src);
};
img.src = issue.pages[i].imageUrl;
}
which works fine, but seems to block downloading of other images: If I call
imageN = new Image();
imageN.src = issue.pages[n].imageUrl;
somewhere else (onClick of thumb) while images of loop still loading, imageN will not be loaded before it's its turn from order in loop.
Any ideas?
To my knowledge there is no way to stop or suspend an image loading with javascript. However, a neat way to control the order of the images loading would be to chain together their load events. Here is an example (using jQuery).
In the example I have an array imgQueue that I am using as a queue and a function loadNextImage that grabs an image off the queue to load and calls loadNextImage when the image is done loading.
function loadNextImage() {
if (imgQueue.length > 0) {
var imgN = new Image();
imgN.src = imgQueue.shift();
$(imgN).load(function(){
$("#main").append(imgN);
loadNextImage();
});
}
}
To change the order images are loading you would literally just move them ahead in imgQueue, for example if I wanted to move image 5 to the front:
imgQueue.unshift(imgQueue.splice(4,1));
This isn't perfect, for instance, unless the images are large it probably makes more sense to load them in groups. Also because loadNextImage manipulates the queue you can't keep track of images just by their original index, you'd need to do something fancy like store them as hashes so you can find them later:
var imgHashQueue = [
{name: "name", url = "url"},
...
]
Couple resources here:
http://ditio.net/2010/02/14/jquery-preload-images-tutorial-and-example/ - http://engineeredweb.com/blog/09/12/preloading-images-jquery-and-javascript
Previous SO discussion: Preloading images with jQuery

Categories