My application is a MVC, using MS SQL to get the image file names. I am using the following script to preload images; would like to know How I can display hourglass cursor while waiting to complete the preload.
function preload_images() {
var i, count = 0;
$('#selector').css('cursor', 'wait');
for (i = 1; i < sl; i++) {
images[i] = new Image();
images[i].onload = images[i].onerror = function () {
count++;
if (count == sl) {
$('#selector').css('cursor', 'default');
}
}
images[i].src = impath.toString() + im.toString() + i + ".jpg";
}
}
It works great first time, however, when I change the file name from a dropdownlist, the hourglass does not stop even all images are load. Thanks in advance.
From the code above you are loading sl-1 images, but the condition to stop the wait cursor is sl images(if (count == sl)), so change it to if (count == (sl-1))
Thanks to Musa for providing the initial solution, here is the way I got it to work, just in case someone is looking for it:
var images = [];
function preload_images() {
showLoadingImage();
$('#selector').css('cursor', 'wait');
for (i = tochar; i < sl; i++) {
images[i] = new Image();
var name = impath.toString() + imStart.toString() + i + ext;
images[i].src = 'ImageHandler.ashx?img=' + name + '&window=50&level=50 &slice=0';
if (i == sl - 1) {
images[i].onload = images[i].onerror = function () {
$('#selector').css('cursor', 'Default');
hideLoadingImage(this);
};
}
}
}
function showLoadingImage() {
$('#imagediv').append('<div id="imagediv1"><img src="../Content/images/ajax-loader2.gif" alt="Loading..." /></div>');
$('#imagediv1').show();
}
function hideLoadingImage(img) {
$('#imagediv1').hide();
img.onload = img.onerror = null;
}
Related
I have a big problem with images in javascript embedded aplications. I want make a preload image but I don't know how the browser works.
See this simple example: code
var colors = [
"http://www.robolaranja.com.br/wp-content/uploads/2014/10/Primeira-imagem-do-filme-de-Angry-Birds-%C3%A9-revelada-2.jpg",
"http://imguol.com/c/noticias/2013/12/13/13dez2013---esta-imagem-mostra-a-nebulosa-de-caranguejo-um-iconico-remanescente-de-supernova-na-nossa-galaxia-vista-do-observatorio-espacial-herschel-e-do-telescopio-hubble-uma-nuvem-de-gas-e-poeira-1386961235961_956x500.jpg",
"http://wallpaper.ultradownloads.com.br/121350_Papel-de-Parede-Imagem-Abstrata_1920x1200.jpg"
]
var currentDiv = "div2";
var count = 0;
var lenght = colors.length;
var timeForNextImage = 0;
var preloadOk = false;
setInterval(function() {
count ++;
if (count > lenght) count = 0;
var date = new Date();
var time = date.getTime();
if (time > (timeForNextImage - 3000) && preloadOk == false) {
preLoad();
} else if (time > timeForNextImage) {
play();
}
}, 300);
var play = function() {
if (currentDiv == "div2") {
$('#'+currentDiv).css("visibility", "visible");
} else {
$('#div2').css("visibility", "hidden");
}
var date = new Date();
timeForNextImage = date.getTime() + 10000;
preloadOk = false;
$("#lbl").text("div atual: "+currentDiv);
};
var preLoad = function() {
if (currentDiv == "div1") {
currentDiv = "div2";
} else {
currentDiv = "div1";
}
$("#" + currentDiv).css("background-image", 'url('+colors[count]+')');
preloadOk = true;
};
How you can look, I do a preload, in theory.. but, the browser only processes my image when I put it in the stage ?
What if I change the z-index attribute, it renders again?
You return preloadOK = true but the image doesn't load. That's not a preloader.
To make a preloader you can play with new Image() object or with load() event.
var images = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
}
preload(
"http://domain.tld/gallery/image-001.jpg",
"http://domain.tld/gallery/image-002.jpg",
"http://domain.tld/gallery/image-003.jpg"
)
See more
3 Ways to Preload Images with CSS, JavaScript, or Ajax
A simple way to preload an image is to just create an image tag and set the url as the src. You don't have to attach it to the DOM to make the request.
var preLoad = function() {
var img = new Image();
img.src = colors[count];
};
I have a javascript which uses many images, and I want to load them all before the user starts clicking around. The images are a little bit big, so it takes a while. Here's my code:
startTest();
function preloadImages() {
console.log("preload images");
for(var i = 1; i <= 132; i++) {
var img = new Image();
images[i-1] = "images/"+i+".png";
img.src = images[i-1];
if(i == 132) {
img.load = doneLoading();
}
}
}
function doneLoading() {
console.log("done loading");
document.getElementById("laading").style.display = "none";
console.log("loading gone");
showReady();
}
function startTest() {
console.log("start test");
trialCount = 0;
document.getElementById("laading").style.display = "block";
preloadImages();
var hammertime = Hammer(document.body).on("touch", function(event) {
registerTouch(event);
});
startTestTime = +new Date();
console.log("end start test");
}
As you can see, startTest() is first called, which calls preload images. Here's the issue:
When I load the page in the browser, the javascript console indicates that "done loading" has been printed, however the spinny wheel on the tab in the browser shows that the webpage is still loading...
What's going on here? How can I figure out once all my images are done loading?
You need to check on each image load that the image is the last one to load. Check using a count variable (loaded).
function preloadImages() {
var loaded = 0;
for(var i = 0; i <= 132; i++) {
var img = new Image();
images.push("images/"+(i+1)+".png");
img.src = images[i];
img.onload = function(){
loaded++;
if(!(loaded < 132)){
// all images have loaded
doneLoading();
}
}
}
}
In order to do a pre-loading, you will have to keep checking the complete status for each image that is being downloaded. Since, you can't know beforehand how much time it will take for each image to download (depending on latency or size), you will have to implement a timer which will keep polling the complete status on each image.
Here is one possible algorithm:
var timer = null,
numImages = 132,
allImages = new Array;
function preLoadImages() {
document.getElementById('loadcaption').innerHTML = 'Loading images... ';
for (var i = 0; i < numImages; i++) {
var tmp = "images/" + i + ".png";
allImages[i] = new Image();
allImages[i].onLoad = imgOnLoad(tmp);
allImages[i].src = tmp;
}
timer = window.setInterval('checkLoadComplete()', 250);
}
function imgOnLoad(imgName) { window.status = 'Loading image... ' + imgName; }
function checkLoadComplete() {
for (var i = 0; i < allImages.length; i++) {
if (!allImages[i].complete) {
imgOnLoad(allImages[i].src);
document.getElementById('loadcaption').innerHTML = 'Loading images... ' + Math.round((i/allImages.length)*100,0) + ' %';
return;
}
}
window.clearInterval(timer);
document.getElementById('loadcaption').innerHTML = 'Completed.';
window.status = '';
}
Where loadcaption is a simple HTML element to show progress. (You can also use an animated gif for loading animation).
The idea is to keep checking the complete status on each image by calling checkLoadComplete by a timer. Once all images are (load) complete, the for loop exits and the timer is cleared.
You start the pre-loading process by calling preLoadImages(); function.
I just started learning Javascript by doing a simple card game and I'm stucked at a problem. I want to show four cards as an image before a user can select a trump by a popup box. But, everytime I run the code the cards images get displayed AFTER the popup box and not before. Please have a look at the relevant code:
function preloadImages() {
var imgs = [];
for (var i = 0; i < max_length_deck; i++) {
imgs[i] = new Image();
imgs[i].src = 'img/' + deck[i] + '.png';
}
}
function generateDeck() {
for (i = 0; i < colour.length; i++) {
for (x = 0; x < number.length; x++) {
deck.push(colour[i] + '' + number[x]);
}
}
}
function shuffleCards() {
cards.length = 0;
for (i = 0; i < max_length_deck; i++) {
var random = Math.floor(Math.random() * deck.length);
cards.push(deck[random]);
deck.splice(random, 1);
}
}
function dealCards() {
generateDeck();
preloadImages();
shuffleCards();
for (var i = 0; i < 4; i++) {
window.document.images[i].src = 'img/' + cards[i] + '.png'; //I defined four image tags at html file
}
selectTrump();
}
function selectTrump() {
var result = false;
while (result != true) {
trump = prompt("Please enter trump:", "");
result = checkTrump(trump);
}
}
I searched and tried several things already (jQuery load handlers; window.setTimeout), but nothing worked and I don't get problem. So, thank you very much for any hint!
BR
Kjaer
In the function Dealcards() you probably have to wait for the images to be loaded first, before dealing the cards. You can use add an eventhandler for this:
<html>
<head>
<script>
function loadImage()
{
alert("Image is loaded");
}
</script>
</head>
<body>
<img src="w3javascript.gif" onload="loadImage()" id="myImage">
</body>
</html>
//Or use:
// example
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
addEvent(
document.getElementById('myImage'),
'load',
function () { alert('image loaded!'); }
);
addEventListener vs onclick
I have a set of images that are frames in an animation like: frame-1.jpg, frame-2.jpg and I have about 400 images.
What I want to do is preload these 400 images before the animation starts.
Usually when preloading images I use the following:
var images = [
'img/nav-one-selected.png',
'img/nav-two-selected.png',
'img/nav-three-selected.png',
'img/nav-four-selected.png'
];
$(images).each(function() {
var image = $('<img />').attr('src', this);
});
But in this instance, listing the images in the var isn't feasible, and I also wish to fire off the start animation once the images have all been loaded.
So far I have the following:
$spinner_currentFrame = 1;
$numFrames = 400;
function preloadImages() {
$($images).each(function() {
var image = $('<img />').attr('src', this);
});
startAnimation();
}
function startAnimation() {
$spinner_loadingAnim = setInterval(function () {
UpdateSpinner();
}, 140);
}
function UpdateSpinner() {
$spinner_currentFrame = $spinner_currentFrame + 1;
if($spinner_currentFrame > $numFrames) {
$spinner_currentFrame = 1;
}
console.log($spinner_currentFrame);
$('#spinner').css("background-image", "url(frame-" + $spinner_currentFrame + ".jpg)");
}
$(document).ready(function() {
preloadImages();
});
So the plan is that I preload images that are from 1 to 400 and then once that's completed then start the animation. How would I build the $images var though?
I've thought about something like:
$images = [];
$frame = 1;
$numFrames = 400;
$($frame).each(function() {
$frame = $frame + 1;
if($frame <= $numFrames) {
$images =+ 'frame-' + $frame + '.jpg';
}
});
But I'm not sure how a) efficient this is and b) how to do the callback once all images have loaded successfully.
You should use a standard javascript for loop instead of the jQuery's foreach. Foreach is wonderful for looping over an array or set of objects, but not in this case. Here is an example, please note that you have to bind the onload event handler before you set the Image object's src property.
UPDATE: added more functions to complete the entire example.
var loaded_images = 0;
var frames = 400;
var images = [];
function preloadImages() {
for (i=0; i < frames; i++) {
images[i] = new Image();
images[i].onload = function() {
loaded_images += 1;
checkLoadingFinished();
}
images[i].src = 'frame-' + i + '.jpg';
}
}
function checkLoadingFinished() {
if (loaded_images >= frames) {
startAnimation();
}
}
function startAnimation() {
var frameNumber = 0;
var timer = setInterval(function() {
$('#img-dom-element').attr('src', images[frameNumber]);
if (frameNumber > frames) {
frameNumber = 0;
else
frameNumber++;
}, (1000/30)); // (1000/30) = 30 frames per second
}
$(document).ready(function() {
preloadImages();
});
I dont know if it fits to your special case but I use
http://thinkpixellab.com/pxloader/
to preload images. You can add the paths and get one callback if all images are loaded. Afterwards you can start animation.
I have several images, the width of each image is 1400px, I want after load all images, alert sum width of all images, this is my code:
var images = new Array("0.jpg", "1.jpg", "2.jpg");
for (var i = 0; i < images.length; i = i + 1) {
$("#img_place").append("<img src='" + images[i] + "'>");
}
var loadedImgsCount = 0;
var imgTotalWidth = 0;
for (var i = 0; i < images.length; i = i + 1) {
var currImg = new Image();
currImg.src = images[i];
currImg.onload = function() {
loadedImgsCount = loadedImgsCount + 1;
imgTotalWidth = imgTotalWidth + currImg.width;
}
}
interv = setInterval(function() {
if (images.length === loadedImgsCount) {
alert(imgTotalWidth );
clearInterval(interv);
}
}, 500);
and in HTML:
<div id="img_place">
</div>
this code is for example for 3 image, problem is that: in chrome and safari, result from this code is sometimes incorrect: sometimes 1400, sometimes 2800 but sometimes correct: 4200.
In opera and firefox resultat always expected: 4200.
Please tell, where have I error? why my code works in safari and chrome incorrect ?
Do the reverse:
currImg.onload = function() {
loadedImgsCount = loadedImgsCount + 1;
imgTotalWidth = imgTotalWidth + currImg.width;
};
currImg.src = images[i];
Your problem is that the onload function may not be called when the images are in cache because the load event is generated before you set the onload callback.
As a side note, it's usual to do this to increment a variable:
loadedImgsCount++;
As long as a width attribute isn't hard-coded, I prefer to check for an image's width to determine if it is loaded. This avoids the caching issues.
var
images = ["0.jpg", "1.jpg", "2.jpg"],
images_place = $("#img_place"),
images_loaded_interval = setInterval(function() {
var total_width = 0;
for (var i = 0; i < images.length; i++)
if($('img',images_place).eq(i).width()*1 == 0) return;
else total_width += $('img',images_place).eq(i).width()*1;
alert(total_width);
clearInterval(images_loaded_interval);
}, 500);
for (var i = 0; i < images.length; i++)
images_place.append("<img src='" + images[i] + "'>");