I'm trying to build a progressive slider with x images. The meaning is, that on page load the slider loads 3 images in slider container, no matter how many images the array contains.
Click on next/prev should slide the first 3 images to either side and then load the next 3 (if any).
It should send the next index number to the next function and increase/decrease on click.
Does this make any sense? :) It is a fast mockup I've made... Any ideas are welcome :O)
THX!!!
var aImages = new Array("image1.jpg","image2.jpg","image3.jpg");
var slideImage = 1;
function showImages()
{
var startImage = (slideImage -1)*6+1;
var endImage = (startImage +5);
for(i=startImage ; i <= endImage ; i++)
{
$('imageId'+ i).src = aImages[i];
slideImage ++;
}
}
function slideImages()
{
var startImage = (slideImage -1)*6+1;
var endImage = (startImage +5);
for(i=startImage ; i <= endImage ; i++)
{
$('imageId'+ i).src = aImages[i];
}
}
slideImages();
To have an optimal experience you should at least preload the previous 3 and the next 3 images
You could also do something like
var imageList = [];
for(...)
{
var img = new Image();
img.src = '';
imageList.push(img);
}
to keep them in cache
and use 9 image placeholders (central 3 plus 3 to each side) and then just apply the
imgNode.src = imageList[x].src
Related
This question already has answers here:
Detect multiple images load event
(2 answers)
Closed 8 years ago.
I have a simple html page where I want to load a stack of images. And I want to display one of them according to the user's cursor on the screen. Basically I'm trying to do something like this :
http://test.vostrel.net/jquery.reel/example/object-movie-camera-sequence/
I do this in two steps, in the first one I load low resolution images (60 images in less than two seconds) and in the second one when the user click for the first time I swap the low res for the high resolution images (60 images in about 10 seconds).
Those are my two functions :
function loadImages() {
var imagesDOM;
for (var j = 0 ; j < directoriesNumber ; j++) {
imagesDOM = new Array();
for (var i = 1 ; i < imageNumber + 1 ; i++) {
images[i] = imageDirectory[j] + "/" + imageBasename + twoDigits(i) + imageExtension;
}
for (var i = 1 ; i < imageNumber + 1 ; i++) {
imagesDOM[i] = new Image();
imagesDOM[i].id = "image" + j + "_" + i;
imagesDOM[i].src = images[i];
$("#cadre").append(imagesDOM[i]);
}
}
}
function loadImagesHigh() {
for (var j = 0 ; j < directoriesNumber ; j++) {
for (var i = 1 ; i < imageNumber+1 ; i++) {
images[i] = imageDirectoryHigh[j] + "/" + imageBasename + twoDigits(i) + imageExtension;
}
for (var i = 1 ; i < imageNumber+1 ; i++) {
$("#image" + j + "_" + i).attr("src",images[i]);
}
}
}
So question is how can I monitor the downloads of the images on the client side : 4 out of 60 images loaded please wait...
I have checked this :
Is there a way to determine when 4 images have been loaded using JS?
But the src are written in the html.
Solution, thanks to Aaron Digulla, is as simple as adding the following event listener before assigning a value to src:
$(imagesDOM[i]).load(function () {
console.log("loaded");
}
);
Thanks for reading.
Before assigning a value to src, attach an event listener to the image. You'll need two global variables which that contain the total image count and the number of images that have been loaded.
The question Is there a way to determine when 4 images have been loaded using JS? contains several examples how the event listener looks like.
[EDIT] OP finally used
$(imagesDOM[i]).load(function () {console.log("loaded")});
I had to do a similar thing recently and I plumped for manual use of jQuery deferred objects. Here's the principle:
//specify imgs to load and create a jQuery deferred object for each
var
imgs_to_load = ['foo', 'bar', 'foo2', 'bar2'], //etc
dfds = imgs_to_load.map(function() { return new $.Deferred; });
//wait for each img to load and resolve its corresponding deferred
imgs_to_load.forEach(function(filename, i) {
var img = $('<img />', {src: filename+'.jpg'}).on('load', function() {
dfds[i].resolve();
});
});
//when all imgs loaded, do something
$.when.apply(null, dfds).then(function() { alert('all done'); });
So we make a deferred object for every image we wish to load. When the image loads, we manually resolve it, and when all deferreds are resolved we move on.
The slideshow will rotate among six images 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg
var showarray = ["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg","6.jpg"];
var i = 0;
for( i = 0; i < 6; i++)
{
// How can I make this script wait for two seconds in this spot
// so the pic is displayed for two seconds?
document.getElementById("imageid").src = showarray[i];
if(i == 5) i = 0;
}
I am also including jQuery in this page if that is another way.
Thanks a lot in advance
Look into the setTimeout() method. Call it like this:
setTimeout(function() {
// change the source of the image here.
}, 1000 /* 1 SECOND */);
You don't want to make it sleep for two seconds. This would take away control from the browser and is pretty bad. Try something like this (I'm bad at JS):
var showarray = ["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg","6.jpg"];
var i = 0;
var newPic;
newPic = function() {
i = i+1 % 6;
document.getElementById("imageid").src = showarray[i];
setTimeout(newPic, 2000);
}
newPic();
I have the current JavaScript problem. I have four divisions next to each other on my website that constantly rotate images on a 10 seconds interval. I need these intervals to keep rotating images at the current interval but start 5 seconds apart from each other in order to obtain a nice waterfall effect. How can I accomplish this using JavaScript?
image of how it looks on my websites' header
This is an example of the code I am currently using to display a single division and handle the rotation of the images.
<div class = "TestRotator">
<img src="http://bushveld.info/wp-content/uploads/2013/07/image1.png" alt="rotating" width="100" height="232" id="rotator">
<script type="text/javascript">
(function () {
var rotator = document.getElementById('rotator'); // change to match image ID
var imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/';
var delayInSeconds = 5;
// set number of seconds delay
// list image names
var images = ['image2.png', 'image3.png', 'image4.png'];
var num = 0;
var changeImage = function () {
var len = images.length;
rotator.src = imageDir + images[num++];
if (num == len) {
num = 0;
}
};
setInterval(changeImage, delayInSeconds * 1000);
})();
</script>
</div>
I've fiddled it a lot! (I changed it big time.)
chenged setInterval() with setTimeout() and many others.
Is this what you wanted?
PS: state holds the 1st image to which the imgs change. and the difference in the timeout (200 milliseconds is in order to just to make some difference in between them, yuo can change it to a round number if you want to).
If I've understood your question correctly, you need something like this:
window.onload = function () {
var // Customable parameters
imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/',
interval = 2, // Interval between "flushes" in seconds. Must be > speed * maxScreens
speed = 0.1, // "Flush" speed in seconds
maxScreens = 4, // amount of used image tags
images = 4, // amount of image sources, can be > maxScreens
dir = 1, // 1 = from left to right, -1 = from right to left
// Program
flush,
target = (dir > 0) ? 1 : maxScreens,
targetOrigo = target,
changeImage = function() {
var img = document.getElementById('rotator' + target),
id = parseInt(img.src.substr(img.src.length - 5, 1), 10) - dir;
if (id < 1) {
id = images;
}
if (id > images) {
id = 1;
}
img.src = imageDir + 'image' + id + '.png';
if (target !== maxScreens - targetOrigo + 1) {
target += dir;
setTimeout(changeImage, speed * 1000);
} else {
target = targetOrigo;
setTimeout(runRotation, interval * 1000);
}
return;
},
runRotation = function () {
setTimeout(changeImage, speed * 1000);
};
setTimeout(runRotation, 1000);
}
A live demo at jsFiddle
Notice, that I've put the function at window.onload, looks better when all the images are already loaded, before the rotation starts.
The snippet doesn't use setInterval() at all, instead it's based on nested setTimeout()s. This way you can avoid a mess, which you might get (depends on used browser), if user visits at other tab and then comes back to your site.
You can play with interval, "flush" speed, number of images you have on the rotation and even how many different images you like to use (max. = 9). You can also switch the direction of the rotation.
If you want to avoid two similar images to be shown at the same time, you can add image5.png to your image folder, and set images = 5.
Also version using an image source array available.
Thanx alot for the input. I solved this issue by adapting the code in this manner...
(function() {
var rotator3 = document.getElementById('rotator3'); // change to match image ID
var imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/';
// set number of seconds delay
// list image names
var images = ['image2.png', 'image3.png', 'image4.png', 'image1.png'];
// don't change below this line
var num = 0;
var changeImage = function()
{
var len = images.length;
rotator3.src = imageDir + images[num++];
if (num == len)
{
num = 0;
}
};
function SwImg() {
var rotate = setInterval(changeImage, 20000);
}
setTimeout(SwImg,15000);
})();
This tweak basically creates an initial delay of 5++ seconds at each division with the standard 20 seconds delay interval between switches, rotating each image in each division 5 seconds after the other. Here is a link to the website , will be done end of this week. Thanks again for the input, really awesome and creative ways of solving this issue!
Cheers
okay so i want if my counter reaches the maximum count, it starts over, with the default counter number which is 0 here is my code:
var picCount = 0; // global
var maxCount = 4;
//Pictures, to add more then 4 pics, add var picFive = "link to image here", var picSix ="bla", you get it.. add in picArray ,picFive and ,picSix
//To change the time delay, change it at the body onload and on the setTimeout
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray = [picOne, picTwo, picThree, picFour]
//
// gets next picture in array
function nextPic() { // check if adding 1 exceeds number of pics in array
if (picCount.length < maxCount.length) {
picCount = (picCount + 1 < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
} else {
picCount = (picCount - maxCount < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
}
}
okay so i hope you guys can help me with this..
That's a lot of messy code.
My fix for an implementation would probably look something like this:
var currentPic = 0;
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray= [picOne,picTwo,picThree,picFour]
function nextPic() {
if (currentPic < picArray.length) {currentPic++;}
else {currentPic = 0;}
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
// repeat this every 10 seconds.
setTimeout('nextPic()',10 * 1000)//setTimeout is here
}
Despite many other issues which I am sure are present in your code, I believe this line is the cause of your particular problem addressed in the question:
if (picCount.length < maxCount.length) {
maxCount and picCount are just numbers. They do not have a length property. Change it to this:
if (picCount < maxCount) {
var currentPic = 0;
var picArray= ["http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg",
"http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png",
"http://www.mupload.nl/img/rl6zeofbb.png",
"http://www.mupload.nl/img/rl6zeofbb.png"];
function nextPic() {
(currentPic < picArray.length) ? currentPic++ : currentPic = 0;
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
}
setTimeout('nextPic()',10 * 1000);
I made a few changes that make your code cleaner.
Some tips:
No need to store your image URLs in vars before putting them in the array. Just initialize your array with them.
Don't repeat yourself. Whenever you find yourself using the exact same code in multiple places, you probably need to rethink how you are approaching the problem.
Look up the "ternary operator". In my opinion it makes simple conditional statements easier to read.
No need to use maxCount - the max count will be the length of your picArray.
Although not usually required, try to end all statements with a semicolon.
Don't mind the elitist attitude some people have, but at the same time, try to research as much as you can before asking a question.
How to set interval or may be timeout through the array, to produce effects for the element every 2 sec for example the 1-st idea is to programm something like this:
for (photoKey in arrBigPhotoes) {
setInterval(function() {
// alert(arrBigPhotoes[photoKey]);
document.getElementById("big_photo").src='/upload/images/'+arrBigPhotoes[photoKey];
}, 2000);
}
But it didn't work properly. May be someone can help me with this task I'll be extremely glad.
I'm also have a jQuery - the resolution may be through this library, but without any plug-ins.
Thanks.
Try something like this -
var photos = ['1.jpg', '2.jpg', '3.jpg'];
var photo_index = 0;
function switchPhoto() {
photo_index = (photo_index + 1) % photos.length;
document.getElementById('big_photo').setAttribute('src', '/upload/images/' + photos[photo_index]);
}
setInterval(switchPhoto, 2000);
You should probably put this inside some kind of document ready event handler
I would suggest you pre-load the images you are trying to display. If the user is on a slow connection, your approach would fail.
var images = new Array();
var counter = 0;
var image = document.createElement("img");
image.onload = function() {
counter++;
};
image.src = <url>;
images.push(image);
The counter is there so that you can determine when all images are properly loaded. Let's say you have six images, then, in your "intervaled" function, you would immediately return if counter < 6.
Your "switcher" function could look this way
var i = 0;
setInterval(function() {
if (counter < 6) return;
i = (i+1) % images.length;
document.getElementById("big_photo").src = images[i].src;
}, 2000);