I am having a bit of an issue with image loading in JavaScript. I want a series of images to load sequentially i.e. image 2 only starts loading when image 1 has completely finished loading.
The problem I am finding is that the JavaScript onLoad method does not fire when the image has completed loading, but when the image starts loading. Therefore the smallest image is always going to be the first to load regardless of where in the queue it is. I have put together a simple example of what i mean in JS fiddle (HTML and JS code is below as well).
Any ideas how I can wait until the image has completely loaded before starting to load the next one - it can't be that hard surely?
Note : I originally wrote it using the jQuery .load function and got the same result which is why I was messing about in raw JS.
HTML code:
<ul>
<li><img src="" alt="image 1" width="210" height="174"></li>
<li><img src="" alt="image 2" width="210" height="174"></li>
<li><img src="" alt="image 3" width="210" height="174"></li>
<li><img src="" alt="image 4" width="210" height="174"></li>
<li><img src="" alt="image 5" width="210" height="174"></li>
</ul>
Load the images
JS code:
var imgArr = [
"http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000038166/images/zine-HP-UK.jpg",
"http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000038166/images/Valentine_UK.jpg",
"http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000038166/images/crop_UK__.jpg",
"http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000038166/images/hitlist_UK--.jpg",
"http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000038166/images/chinese_new_year_UK_new_0402.jpg"
],
totalImgs = imgArr.length,
count = 0;
function onLoaded(count) {
console.log("fired onload "+count);
var currentImg = $('li:eq('+count+') img');
currentImg.attr('src', imgArr[count]).css('display','block');
count++;
if (count < totalImgs) {
loadImg(count);
};
}
function loadImg(count) {
imgObj = new Image()
imgObj.src = imgArr[count];
imgObj.onLoad = onLoaded(count);
}
$('#loader').click(function() {
loadImg(count);
});
The problem here is that not the handler function is assigned to the onload event of the Image but the return value of onLoaded. You'd need to say imgObj.onload = onLoaded; For the currentImg you can use this as the handler will be invoked on the Image object. For passing other parameters, an alternative way is needed.
Am sure you moved on from this error seeing it was asked over 2yrs ago; nonetheless I think for the benefit of others I will point out what I believe is your mistake.
You're using imgObj.onLoad instead of imgObj.onload. Javascript is case-sensitive and there is no native "onLoad" event.
The rest of the code should work well when you fix this.
Related
I put my code here and in jsfiddle for test, the test it´s here :
https://jsfiddle.net/efuw4oh3/4/
And my code it´s :
HTML
<img class="img0" src="https://i.pinimg.com/564x/4f/b7/0c/4fb70c8f19424fb03c957c9e8081357e.jpg" style="display:none;" width="100" height="100"/>
<img class="img1" src="https://i.pinimg.com/750x/28/4c/44/284c443c6c886c905ca8513a0b13ba29.jpg" style="display:none;" width="100" height="100"/>
<img class="img2" src="https://i.pinimg.com/564x/4f/b7/0c/4fb70c8f19424fb03c957c9e8081357e.jpg" style="display:none;" width="100" height="100"/>
<img class="img3" src="https://i.pinimg.com/750x/28/4c/44/284c443c6c886c905ca8513a0b13ba29.jpg" style="display:none;" width="100" height="100" />
MY SCRIPT
<script>
i=0;
$(document).ready(function(){
loading();
});
function loading(){
if(i==5){
i=0;
}
///jQuery("#text").show(1000).hide(1000,function(){reloading();});
jQuery(".img"+i).show(1000).hide(1000,function(){reloading();});
}
function reloading(id){
setInterval("loading()",2000);
//alert("ok"+i);
i++;
}
</script>
The problem basically it´s the images start and show well and the third time, show all images at the same time, and irregular order, i don´t know why because the load of images must be in order, when animation 1 end start the next, etc, and i don´t know why do this
Thank´s for the help, best regards community
The problem you're having is - on the "hide" event you're setting another interval. So, the longer it runs, the more slideshow intervals you'll have running creating this effect.
You should have one slideshow interval that handles the showing/hiding and the increment of the image.
/// Current image
let i=0;
$(document).ready(function(){
loading();
});
function loading(){
// Starts our slideshow
setInterval(startSlideShow, 2000);
}
function startSlideShow(){
/// Shows the image
$(".img"+i).show(1000).hide(1000);
/// Increments
i++;
/// Checks if we're beyond how many images we have.
if(i === 4) i = 0;
}
Fiddle
I am trying to set the image source of an image object with javascript.
I have tried
<img src="" id="image" alt="">
<p id="change">Change</p>
$("#change").click(function () {
$("#image").attr("src", "some source");
});
The problem is that it seems it does change the src, but it doesn't work if the image wasn't loaded when the page loaded. So I cannot suddenly change to the logo of Stackoverflow. Can this be true? How can I then load the image while changing the source?
I had an issue similar to this a couple weeks ago, the easiest way I managed to solve the issue was by loading all image's you will need, and set all of the ones you don't need right away as hidden. Then when your action that causes the change is triggered, you can change the image visibility on the one you want to disappear and the one you want to be shown.
If you have bootstrap installed, it is as easy as adding and removing a class via jQuery
HTML
<img src="" id="image1" alt="">
<img src="" id="image2" alt="" class="hidden">
<p id="change">Change</p>
Javascript
$("#change").click(function () {
$('#image1').addClass('hidden');
$('#image2').removeClass('hidden');
});
I am trying to mouseover a thumbnail image and have the larger image of that thumbnail appear below. I know I can target each thumbnail individually, but I would like to use 'this' so I am able to apply the code to any image that I add later. Explanations are greatly appreciated. Thank you! :)
HTML CODE
<div id="gallery">
<ul>
<li><img id="image1" src="images/image1-thumbnail.jpg" alt="#"></li>
<li><img id="image2" src="images/image2-thumbnail.jpg" alt="#"></li>
<li><img id="image3" src="images/image3-thumbnail.jpg" alt="#"></li>
</ul>
<img id="main-image" src="images/image1.jpg" alt="#">
</div>
Javascript Code
This is how I was originally trying to do it. I gave a class of 'image' and 'data-' to each anchor tag (this isn't written in the above HTML code), but it only applies the changes to one thumbnail (whatever number I replace [0] with, and I don't know how to add more numbers), but I believe the best way to achieve what I'm looking to do is by using 'this' and I don't know how to use it.
var image = document.getElementsByClassName('image')[0];
var mainImage = document.getElementById('main-image');
image.onmouseover = function () {
mainImage.src = image.getAttribute('data-mainimage');
mainImage.alt = image.alt;
};
var image = document.getElementsByClassName('image');
var mainImage = document.getElementById('main-image');
[].forEach.call(image,function(img){
img.onmouseover = function(){
mainImage.src = img.parentNode.href;
};
});
getElementsByClassName returns a set of elements, so you have to iterate over them..
I am using .load() in jQuery to load in html content, but in this content there are 3/4 images embedded. The success event only fires on .load() when all the html is loaded in and not actually the images, does anyone know a way of preloading the full content of a page?
$('#ajax_loader').hide().load('page.html',function(){
$(this).fadeUp(1000);
});
This is my simple code (rest of it is in the full app), loading in the following code (ie. page.html)
<div>
<div id="slideshow">
<img src="images/img1.jpg" />
<img src="images/img2.jpg" />
<img src="images/img3.jpg" />
</div>
<p>This is some sample content</p>
</div>
I suggest that you don't use a fadeIn animation after the images are loaded because of performance degradation it brings. It is usually a good idea to fadeIn the content then start loading the images to ensure that the animation is smooth for as many users as possible.
Having said that, of course you can accomplish your original goal if you want to stick with it:
Use a 1x1 blank image as the image src attribute and store the real url in the title.
<div>
<div id="slideshow">
<img src="blank.gif" title="images/img1.jpg" />
<img src="blank.gif" title="images/img2.jpg" />
<img src="blank.gif" title="images/img3.jpg" />
</div>
<p>This is some sample content</p>
</div>
And your code becomes:
$('#ajax_loader').hide().load('page.html', function(){
var c = 0;
var images = $("#slideshow img");
images.load(function(){
if (++c == images.length) {
$('#ajax_loader').fadeIn(1000);
}
});
images.each(function(){
this.src = this.title;
});
});
The images are loaded with separate HTML requests, and obviously the browser can't even start loading them until the HTML in the response has been parsed.
If you know the URLs of the images before you load the content, then you can preload them by creating "Image" elements and waiting for them to load (that is, by handling their "load" events individually).
var imgUrls = [ "images/img1.jpg", "images/img2.jpg", "images/img3.jpg" ];
var c = 0;
for (var i = 0; i < imgUrls.length; ++i) {
var img = new Image();
img.onload = function() {
c += 1;
if (c == imgUrls.length) {
// at this point all images are loaded
// ...
}
};
img.src = imgUrls[i];
}
edit — #galambalazs pointed out that the closure around the handler was (in this case) unnecessary.
Check out this similar situation
It seems that the main fix to your problem would be the correct use of the .ready and the .load operator. If used properly, you can wait until all elements and media items are loaded into the browser before a response is passed to its handler. I don't want to plagerize too much :) and its a really great answer.
I have a series of photos (3 series actually) that need to cycle, which the jQuery cycle plugin does nicely for me.
My problem is I also want to rotate them (rotate as in turn) by a few degrees each in varying directions on page load, to achieve a 'scattered' look. jQuery Rotate does this nicely too ... my problem is I can't get both rotate and cycle to happen on the same page.
It looks as if the solution is going to involve rotating the images within the cycle code itself, but that is beyond my limited capability (at least in the time available). Has anyone else tried this? Got any pointers?
If all else fails, I can pre-rotate the images in photoshop but that's not ideal--the js rotate would mean the photos can be easily refreshed by the site's owner simply dumping new ones in a directory. Photoshop otoh would mean rotating each one -and- converting them from jpg to a format that supports transparency (or even worse, duplicating the appropriate background colours etc in the right places).
I'm using standard jquery.cycle... html pre-loads 1st 3 images like this:
<div id="slideshow" class="pics">
<img class="rotate" src="images/image1.jpg" width="100" height="100" />
<img class="rotate" src="images/image2.jpg" width="100" height="100" />
<img class="rotate" src="images/image3.jpg" width="100" height="100" />
</div>
And I have the usual js that kicks off the cycle:
$(document).ready(function() {
var stack = [];
var imagesPath = '../images/image';
if(window.location.href.indexOf('\/html\/') == -1)
imagesPath = 'images/image';
for (var i = 0; i < 8; i++) {
var img = new Image(100,100);
img.src = imagesPath + i + '.jpg';
$(img).bind('load', function() {
stack.push(this);
});
}
// start slideshow
$('#slideshow').cycle({
timeout: 600,
before: onBefore ,
speed: 2000
});
// add images to slideshow
function onBefore(curr, next, opts) {
if (opts.addSlide) // <-- important!
while(stack.length)
opts.addSlide(stack.pop());
};
});
The js to rotate the first of these images with jQuery.rotate is:
$('.rotate')[0].rotateLeft(5);
The above works if I disable cycling, but nothing happens when cycling is on.
Removing the array reference per the following rotates the visible image, removes it from the slideshow, and leaves it on the page.
$('.rotate').rotateLeft(5);
Perhaps the ideal would be to rotate the containing div instead, but jquery.rotate uses canvas and so only works on images. Let me know if there's any more info I can provide. And thanks for your interest!
JQuery Cycle adds a lot of CSS to the immediate child images of a container in order to turn them into slides. If you want to scatter images on a slide, you should wrap the contents of each slide in a tag. Then tell JQuery cycle that those elements are, in fact, slides by using the slideExpr option.
Html
<div id="slideshow">
<div class="slide">
<img src="1.png" />
<img src="2.png" />
<img src="3.png" />
</div>
<div class="slide">
<img src="1.png" />
<img src="2.png" />
<img src="3.png" />
</div>
</div>
Javascript
$('#slideshow').cycle({
slideExpr: '.slide',
timeout: 600
});
This will allow Jquery cycle to apply it's styles to the wrappers, and JQuery rotate to apply rotations to the contents inside each slide without stepping on each others' toes.
Here's the complete list of JQuery Cycle options.
try using the CSS3 transform selector:
-webkit-transform: rotate(-15deg);
$('.rotate').css({'-webkit-transform' : 'rotate(-5deg)' });