Slow loading of page javascript - javascript

I have this javascript code.
<!-- //////////////////// IMAGE 1 //////////////////// -->
var i = 1;
var Imgt2e10 = Array.apply(null, new Array(10)).map(function() {
var img = new Image();
img.src = "img/t2/t2e10/"+(i++)+".jpg"
return img
});
function RollOvert2e10(i) {
document.t2e10.src=Imgt2e10[i].src;
}
<!-- //////////////////// IMAGE 2 //////////////////// -->
var i = 1;
var Imgt2e2 = Array.apply(null, new Array(10)).map(function() {
var img = new Image();
img.src = "img/t2/t2e2/"+(i++)+".jpg"
return img
});
function RollOvert2e2(i) {
document.t2e2.src=Imgt2e2[i].src;
}
<!-- //////////////////// IMAGE 3 //////////////////// -->
var i = 1;
var Imgt2e3 = Array.apply(null, new Array(10)).map(function() {
var img = new Image();
img.src = "img/t2/t2e3/"+(i++)+".jpg"
return img
});
function RollOvert2e3(i) {
document.t2e3.src=Imgt2e3[i].src;
}
Each of these bits of code applies to one image. In this example I have 3 images but in my website I have more than 50 and it's taking too long to load the web page.
Is it because I'm repeating the code over and over or because I have too many images (small jpg's) loading at the same time?
How can I make this code shorter and elegant? Or at least the loading faster...
Any help is appreciated!

As we discussed previously, the slowdown is most certainly caused by the size of the images. Now for some less cumbersome JS code, I would propose something like that:
function Loader (basename)
{
this.image = {};
this.basename = basename;
}
Loader.prototype = {
load: function (name)
{
this.image[name] = new array(10);
for (var i = 0 ; i != 10 ; i++)
{
this.images[name][i] = new Image ();
this.images[name][i].src = "img/"+basename+"/"+name+"/"+i+".jpg";
}
},
rollover: function (name, index)
{
document[name].src = image[name][index].src;
}
}
var loader = new Loader("t2"); // create a loader for the t2 folder
loader.load ("whatever"); // load an image collection
loader.rollover ("whatever", 5); // roll over to the 5th image

Related

Drawing an array of images on canvas in javascript [duplicate]

So I have been recently developing a site, The problem is the backgrounds for each page are images, and as a result, on slower connections (which is the case of some of the target audience) the images load progressivly as they are downloaded, to resolve this I am trying to make a preloading page that does the following :
Loads the Images
Once the loading is done, redirects the user to the requested page
<script type="text/javascript">
<!--//--><![CDATA[//><!--
var images = new Array()
var count=0;
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
if(count==4) {
window.location = "index.html";
}
}
preload(
"backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"
)
//--><!]]>
The problem is it redirects directly (I assume that it just starts the download of the image then directly adds one to the counter variable, quickly reaching 4 and not giving the image the time to download.
Any ideas how I can either make it signal me when the images have finished downloading, or only execute the redirect after it has done downloading the images ?
You need to wait for the load event. It's quite simple:
function preload(images, timeout, cb) {
var cbFired = false,
remaining = images.length,
timer = null;
function imageDone() {
remaining--;
if(remaining === 0 && !cbFired) {
cbFired = true;
clearTimeout(timer);
cb();
}
}
function timerExpired() {
if(cbFired)
return;
cbFired = true;
cb();
}
for(var i = 0; i < images.length; i++) {
var img = new Image();
img.onload = imageDone;
img.onerror = imageDone;
img.src = images[i];
}
timer = setTimeout(timerExpired, timeout);
}
You need to check a few things so that users don't get stuck:
You need to wait for both load and error so that the page doesn't get stuck if an image fails to load.
You should set a maximum timeout.
Also, in your code, i was a global variable (no var declaration).
Here's how to use it:
var images = [ "backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"];
preload(images, 10000 /* 10s */, function () {
window.location = 'next_page';
});
Modify your preloader so that it binds to the "onload" event of the Image object and when all callbacks are fired it redirects (untested sample code below):
var images = new Array()
var count = 0;
function preload() {
var numImages = preload.arguments.length
for (i = 0; i < numImages; i++) {
images[i] = new Image();
images[i].onload = doneLoading; // See function below.
images[i].src = preload.arguments[i];
}
function doneLoading() {
if (++count >= numImages) {
window.location = "index.html";
}
}
}
preload(
"backgrounds/bg1.jpg",
"backgrounds/bg2.jpg",
"backgrounds/bg3.jpg",
"backgrounds/bg4.jpg"
)

how to use drawImage after load all images in array

I want to draw image array with drawImage after all the images are loaded.There is a render problem with drawImage(), tried to solve with setTimeout() but its not working all the time.
Here is my code;
while(FocusItem.length>0)
{
FocusItem.pop();
}
ftx=canvas.getContext('2d');
focusImageBackground = new Image();
focusImageBackground.src = "./images/odaklanma/odaklanmaBackground.jpg";
if(RandomSoru==15)
finishSoru=true;
if(finishSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
tempRandomSoru=RandomSoru;
}
if(RandomSoru==tempRandomSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
}
var soru = new Object();
soru["image"] = new Image();
soru.image.src = './images/odaklanma/level/'+RandomSoru+'/soru.png';
soru["x"] = 341;
soru["y"] = 140;
FocusItem.push(soru);
var dogru = new Object();
dogru["image"] = new Image();
dogru.image.src = './images/odaklanma/level/'+RandomSoru+'/dogru.png';
dogru["x"] = xDogru;
dogru["y"] = 280;
FocusItem.push(dogru);
var yanlis = new Object();
yanlis["image"] = new Image();
yanlis.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis.png';
yanlis["x"] = xYanlis1;
yanlis["y"] = 280;
FocusItem.push(yanlis);
var yanlis2 = new Object();
yanlis2["image"] = new Image();
yanlis2.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis1.png';
yanlis2["x"] = xYanlis2;
yanlis2["y"] = 280;
FocusItem.push(yanlis2);
}
if(focusImageBackground.complete){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
else
focusImageBackground.onload=function(){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
function drawFocus(){
ftx.drawImage(focusImageBackground,0,0);
for (var i=0; i<FocusItem.length; i++){
FocusItem[i].image.onload=function(){
ftx.drawImage (FocusItem[i].image, FocusItem[i].x, FocusItem[i].y);
}
}
}
I'd suggest loading all your images, then when they are all done, you can call the rest of your code. I don't quite follow what you're trying to do with all the rest of your code, but here's a simple way to load an array of image URLs and know when they are done.
This is the general idea (I've left out lots of your code that has nothing to do with the central issue of knowing when all the images are loaded) and I've also tried to DRY up your code:
function createImagesNotify(srcs, fn) {
var imgs = [], img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
imgs.push(img);
img.onload = function() {
--remaining;
if (remaining == 0) {
fn(srcs);
}
};
// must set .src after setting onload handler
img.src = srcs[i];
}
return(imgs);
}
// here's your starting array of filenames
var fnames = ["soru.png", "dogru.png", "yanlis.png", "yanlis1.png"];
// insert your process to create RandomSoru here
var randomSoru = ....;
// build full urls array
var urls = [];
for (var i = 0; i < fnames; i++) {
urls.push('./images/odaklanma/level/' + RandomSoru + '/' + fnames[i]);
}
// load all images and call callback function when they are all done loading
var imgs = createImagesNotify(urls, function() {
// all images have been loaded here
// do whatever you want with all the loaded images now (like draw them)
});
This code is based on an earlier answer of mine here: Cross-browser solution for a callback when loading multiple images?

how to check if all images loaded? (no jQuery please)

Due to the nature of async execution in .onload, Javscript would not run in the order as appeared in the code. Following snippet as I leared from how to alert after all images loaded? would not work always, pass here and fail there, all depending on the sequence of browser execution. Any suggestion how to solve it? (no jQuery please, nor asking me why)
var imgLoaded = 0;
var imgToLoad = 10;
var onImgLoad = function()
{
imgLoaded++;
if(imgLoaded == imgToLoad)
{
alert("done"); //Call to our draw function
}
}
for(var i = 0; i < 10; i++)
{
images[i] = new Image();
images[i].onload = onImgLoad;
images[i].src = 'images/'+i+'.png';
}
Specifically, here is where the code fails:
imgLoaded++;
if(imgLoaded == imgToLoad) { }
As a result, sometimes the code in the IF condition might not get executed even if all images were loaded corrected.
See this fiddle : http://jsfiddle.net/wdBbX/
var images = [];
function loadImages(callBack)
{
var imgLoaded = 0;
var imgToLoad = 10;
var onImgLoad = function()
{
imgLoaded++;
if(imgLoaded == imgToLoad)
{
callBack(imgLoaded); //Call to our draw function
}
}
for(var i = 0; i < 10; i++)
{
images[i] = new Image();
images[i].onload = onImgLoad;
images[i].src = 'images/'+i+'.png';
}
}
loadImages(function(i){
alert(i);
});
i prefer the sequentially way in this case.
so you can add cool animations with css...
var current=1,toload=10;
function next(){
var img=document.createElement('img');
img.onload=function(){
current++;
current==(toload+1)?(
console.log('ALL IMAGES ARE LOADED');
// callback
):(
next()
)
document.body.appendChild(this);
}
img.src='img/'+current+'.jpg';
}
window.onload=next;
i also added the way to addan image array
var current=0,images=['img1.jpg','img2.jpg','img3.jpg','img4.jpg'];
function next(){
var img=document.createElement('img');
img.onload=function(){
current++;
current==images.length?(
console.log('ALL IMAGES ARE LOADED');
// callback
):(
next()
)
document.body.appendChild(this);
}
img.src=images[current];
}
window.onload=next;
if your not shure about all images add also a img.onerror with the same function as onload esle the loop stops.
if you don't understand something or you need it as a callback function just ask.
Here is a proper up-to-date solution, including example usage:
const preload = src => new Promise(function(resolve, reject) {
const img = document.createElement('img');
img.onload = function() {
resolve(img);
}
img.onerror = reject;
img.src = src;
});
const preloadAll = sources =>
Promise.all(
sources.map(
preload));
const sources = [
'https://i.picsum.photos/id/1000/5626/3635.jpg',
'https://i.picsum.photos/id/10/2500/1667.jpg',
'https://homepages.cae.wisc.edu/~ece533/images/cat.png',
'https://homepages.cae.wisc.edu/~ece533/images/airplane.png'
];
preloadAll(sources)
.then(images => console.log('Preloaded all', images))
.catch(err => console.error('Failed', err));
From here.

Why doesn't this Javascript image object get added to the image array?

I've been trying to create a small HTML5-based example, but I've ran into some problems. I want to render a rock on a <canvas> but this Javascript object won't work properly.
function ImageData() {
this.image_names = ["rock1"];
this.images = new Array();
this.loadResources = function () {
for (var i = 0; i < this.image_names.length; i++) {
var img = new Image();
img.onload = (function (a) {
a.images[a.image_names[i]] = img;
console.log(a.images); //log is successful, image is in array
})(this);
img.src = "images/" + this.image_names[i] + ".png";
}
}
}
It's use is to be as follows:
var a = new ImageData();
a.loadResources();
var rock1_image = a.images["rock1"]; //the "rock1.png" image
If you try accessing the object via console, you'll see that there is no image in the image array, after being certain the image loaded. I can't figure out why it's not working. I've looked over it multiple times.
EDIT: Here is my final, working result:
function ImageData() {
this.image_names = ["rock1"];
this.images = new Array();
this.loadResources = function (callback) {
for (var i = 0; i < this.image_names.length; i++) {
var img = new Image();
img.onload = (function (a, i) {
return function() {
a.images[a.image_names[i]] = img;
if (i == (a.image_names.length - 1)) callback();
};
})(this, i);
img.src = "images/" + this.image_names[i] + ".png";
}
}
}
I would venture to say that you are attempting to access it before it is added to your array. I would suggest adding a callback or something to your loadResources method to make sure that it's there before you attempt to access it.
this.loadResources = function (callback) {
for (var i = 0; i < this.image_names.length; i++) {
var img = new Image();
img.onload = (function (a, i) {
return function() {
a.images[a.image_names[i]] = img;
console.log(a.images); //log is successful, image is in array
callback();
};
})(this, i);
img.src = "images/" + this.image_names[i] + ".png";
}
}
then
var a = new ImageData();
var rock1_image;
a.loadResources(function() {
rock1_image = a.images["rock1"];
// do whatever you need to do with the image in here.
});
Also, what #Igor mentions. I totally missed that. I adjusted the code above so you could keep your this scope without having to set it elsewhere.
Updated to take care of the i issue brought up by #RobD.
Remove (this) after onload handler definition. You are actually calling this function right away, assigning undefined (since it returns nothing) as img.onload value.
In the code:
> function ImageData() {
> this.image_names = ["rock1"];
> this.images = new Array();
> this.loadResources = function () {
> for (var i = 0; i < this.image_names.length; i++) {
> var img = new Image();
> img.onload = (function (a) {
This function will be run immediately and does not return a value, so undefined will be assigned. So no point in the assignment, just run the code.
> a.images[a.image_names[i]] = img;
Images is an array that is used as a plain object. Better to use a plain object then.
> console.log(a.images); //log is successful, image is in array
> })(this);
The outer this must be passed in because of the IIFE. Remove the IIFE and there is no requirement to pass this. And if a reference to the instance is stored in the function, it won't matter how the function is called (i.e. you won't have to set this in the call).
> img.src = "images/" + this.image_names[i] + ".png";
> }
> }
> }
You might want something like:
function ImageData() {
this.image_names = ['rock1'];
this.images = {};
imageData = this;
this.loadResources = function (callback) {
for (var i = 0; i < imageData.image_names.length; i++) {
var img = new Image();
imageData.images[a.image_names[i]] = img;
img.src = 'images/' + this.image_names[i] + '.png';
if (callback) {
img.onload = callback;
}
}
}
}
var a = new ImageData();
a.loadResources(function(){console.log('loaded: ' + this.src);}); // loaded: …
window.onload = function() {
document.body.appendChild(a.images.rock1); // image appears in document
}
I haven't tested your code yet, but I guess this is the problem:
You are trying to access your image before it was loaded. You can use callback event handler after it was load like:
var data = new ImageData();
data.loadResources(function(imgObj){
// imgObj is the newly load image here. Have fun with it now!
})

Javascript Array with Links

I am using an javascript array to swap images and act like a slide show. I am looking to apply an image map to each image and link to a specific page when clicked.
I need to code an image map hot spot covering a rectangle from (24,247) to (174,284) becomes a link. But I need each image to link to a different page (the hotspot location remains the same on every image.) How do I program this so when each image changes in the slide show it links to a different page?
Here is the coding involved:
in Head Section (js file listed far below):
<style> #Slideshow1 img {height:356px; width:912px}</style>
<script type="text/javascript" src="js/slideshowmerge.js"></script>
In the HTML Section to place array:
<div class="box_broadstyle">
<script>
var imgArray = new Array();
imgArray[0] = "images2/slide_pics/full/ashley.png";
imgArray[1] = "images2/slide_pics/full/auburn.png";
imgArray[2] = "images2/slide_pics/full/brooklyn.png";
imgArray[3] = "images2/slide_pics/full/cobane.png";
imgArray[4] = "images2/slide_pics/full/giddeon.png";
imgArray[5] = "images2/slide_pics/full/hartford.png";
imgArray[6] = "images2/slide_pics/full/saratoga.png";
imgArray[7] = "images2/slide_pics/full/seabrook.png";
imgArray[8] = "images2/slide_pics/full/spring.png";
slideshowMerge('Slideshow1','',imgArray,20,5000);
</script><
</div>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
Slideshowmerge.js listed here:
//=======================
//
// Merging Image Slideshow
//
//
//=======================
var slideshowMergeAnimate = new Array();
var slideshowMergeTimer = new Array();
var slideshowMergeCount = new Array();
var slideshowMergeImages = new Array();
//======================
function slideshowMerge(id,cl,imageArray,fadeInterval,holdTime)
{
for(i=0;i<imageArray.length;i++)
{
var imgLoad = new Image();
imgLoad.src = imageArray[i];
}
if(cl)
cl = ' class="'+cl+'"';
document.write('<div id="'+id+'"'+cl+' style="position:relative">');
document.write('<img id="'+id+'img1" style="position:absolute; top:0px; left:0px;" onload="slideshowMergeRun(\''+id+'\')"/>');
document.write('<img id="'+id+'img2" style="position:absolute; top:0px; left:0px;display:none;"/></div>');
slideshowMergeCount[id] = 0;
slideshowMergeImages[id] = imageArray;
slideshowMergeAnimate[id] = 'run';
slideshowMergeTimer[id] = setInterval('slideshowMergeAnimation(\''+id+'\',\''+holdTime+'\');',fadeInterval);
}
//======================
function slideshowMergeAnimation(id,holdTime)
{
if(slideshowMergeAnimate[id]=='run')
{
var obj1 = document.getElementById(id+'img1');
var obj2 = document.getElementById(id+'img2');
var opa = slideshowMergeCount[id]%100;
if(opa==0)
{
if(obj1.src)
{
slideshowMergeAnimate[id] = 'hold';
setTimeout('slideshowMergeRun(\''+id+'\')',holdTime);
obj2.src = obj1.src;
obj2.style.display = 'block';
}
}
else if(opa==1)
{
slideshowMergeAnimate[id] = 'load';
obj1.src = slideshowMergeImages[id][Math.floor(slideshowMergeCount[id]/100)%slideshowMergeImages[id].length];
}
obj1.style.opacity = (opa/100).toString();
obj1.style.filter = "alpha(opacity="+opa.toString()+")";
obj2.style.opacity = ((100-opa)/100).toString();
obj2.style.filter = "alpha(opacity="+(100-opa).toString()+")";
slideshowMergeCount[id]++;
if(slideshowMergeCount[id]==(slideshowMergeImages[id].length*100))
slideshowMergeCount[id]=0;
}
}
//======================
function slideshowMergeRun(id)
{
slideshowMergeAnimate[id] = 'run';
}
//======================

Categories