How to change images src automatically - javascript

I have been trying to code a traffic light sequence that will loop through the images automatically. However, I have a small problem with the automatic changing. Could you help with where I am going wrong?
var images = ["red.png",
"redamber.png",
"orange.png",
"green.png"];
setTimeout("changelight()",1000);
var index = 0;
function changeImage()
{
document.getElementById("img").src= images[0];
}

Please check the Fiddle
Try this
var index = 0;
function changeImage()
{
if (index > 3) index = 0;
document.getElementById("img").src= images[index];
index++;
}
var images = ["red.png",
"redamber.png",
"orange.png",
"green.png"];
setInterval(changeImage,1000);

You probably intended
document.getElementById("img").src= images[index];
And make sure that index is updated

You were mostly there, but there were a couple of little things.
Firstly, you were calling a function called changeLight, but the function was called changeImage. You also need to change the image source attribute to images[index], and then increase that value each time.
The line index = (index + 1) % 4; adds 1 to index, but will only allow it to get as high as 3. If it reaches 4 then the % 4 at the end will set it to 0.
For reference, see the remainder description on this page
You were also using setTimeout which only runs once. If you use setInterval it works exactly the same but repeats.
var images = ["red.png",
"redamber.png",
"orange.png",
"green.png"];
setInterval(changeLight, 1000);
var index = 0;
function changeLight() {
document.getElementById("img").src = images[index];
index = (index + 1) % 4;
}
The only other thing that may be an issue is that I don't know if your image actually does have an ID of img. If it doesn't then you'll need to add that.

You did some typical beginner mistakes:
Your function name isn't related with the one in the timer.
You probably want an interval instead of a single timeout.
You have to use a querySelector to select a DOM by tag.
To go through an array you have to use variable increment combined with an if check.
Please read the doc's: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide
var images = ["red.png", "redamber.png", "orange.png", "green.png"];
var index = 0;
setInterval(function(){
document.querySelector("img").src= images[index];
/* common - easy to understand - way:
if (index > images.length - 1) index = 0;
...
index++;
*/
index = index == images.length - 1 ? index = 0 : index + 1 // casual way - toggle bool -
console.log(index);
}, 1000);
Example: https://jsfiddle.net/27jygopz/

var images = ["red.png", "redamber.png", "orange.png", "green.png"];
setTimeout("changelight()",1000);
var index = 0;
function changeImage()
{
index = (index + 1) % 4;
document.getElementById("img").src= images[index];
}

Related

How do I use JavaScript to change the src of an <img> in a set cycle of multiple images

I need to have an image change through a set series as a button is clicked. How the JavaScript works is that it checks for which the current src matches and then changes it to whatever image is assigned to it. Where is the mistake?
function cycleImage() {
var currentImage = document.getElementById("img-slide").src;
if(currentImage == "/images/image-1.jpg") {
document.getElementById("img-slide").src = "/images/image-2.jpg";
}
else if(currentImage == "/images/image-2.jpg") {
document.getElementById("img-slide").src = "/images/image-3.jpg";
}
else if(currentImage == "/images/image-3.jpg") {
document.getElementById("img-slide").src = "/images/image-4.jpg";
}
else if(currentImage == "/images/image-4.jpg") {
document.getElementById("img-slide").src = "/images/image-1.jpg";
}
}
If you look at currentSource, you'll see that it's a fully-resolved URL (like https://example.com/images/image-1.jpg, not a relative URL (like /images/image-1.jpg), so it won't match any of the strings you're comparing it with. That's because the src property provides a full-resolved URL, not the literal value of the src attribute.
While you could use endsWith to do the comparison instead (or use getAttribute to get the actual attribute value), I wouldn't do it that way. Instead, I'd keep track in a variable:
let imageIndex = 1;
setImage();
function setImage() {
document.getElementById("img-slide").src = `/images/image-${imageIndex}.jpg`;
}
function cycleImage() {
imageIndex = (imageIndex % 4) + 1;
setImage();
}
Live Example (using div elements instead of images):
let imageIndex = 1;
setImage();
function setImage() {
document.getElementById("img-slide").textContent = `/images/image-${imageIndex}.jpg`;
}
function cycleImage() {
imageIndex = (imageIndex % 4) + 1;
setImage();
}
setInterval(cycleImage, 800);
<div id="img-slide"></div>
That imageIndex = (imageIndex % 4) + 1; thing is a useful trick: it increments a 1-based number, wrapping back around to 1 after it's had a given maximum value (in this case, 4). So we get 1 2 3 4 1 2 3 4.... (You don't strictly need the () in it, but it's useful for understanding how it works.)
Or if the image paths weren't easily generated like that, I'd use an array of images paths and loop through it:
const images = [
"/something.jpg",
"/something-else.png",
"/a-different-thing.jpg",
"/yet-another-thing.jpg",
// ...
];
let imageIndex = 0;
setImage();
function setImage() {
document.getElementById("img-slide").src = images[imageIndex];
}
function cycleImage() {
imageIndex = (imageIndex + 1) % images.length;
setImage();
}
Live Example (using div elements instead of images):
const images = [
"/something.jpg",
"/something-else.png",
"/a-different-thing.jpg",
"/yet-another-thing.jpg",
// ...
];
let imageIndex = 0;
setImage();
function setImage() {
document.getElementById("img-slide").textContent = images[imageIndex];
}
function cycleImage() {
imageIndex = (imageIndex + 1) % images.length;
setImage();
}
setInterval(cycleImage, 800);
<div id="img-slide"></div>
That imageIndex = (imageIndex + 1) % images.length is another useful trick similar to the one above. It increments a 0-based value, wrapping it around back to 0 when (before) it reaches a maximum value (in this case, images.length, which is 4). So we get 0 1 2 3 0 1 2 3.... (You do need the ()in this one, because%has a higher precedence than+`.)

SetInterval wont work? button still has to be pressed each time

I need the images to change from one to another each time the button is pressed. I have tried using SetTimeout, setInterval etc and none of these seem to work? Im not sure what I'm doing wrong
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index = index + 1;
if (index == list.length)
index = 0;
var myVar = setInterval(function() {
ChangeLights()
}, 1000);
}
}();
<button type="button" onclick="changeLights()">Change Lights</button>
You are calling ChangeLights instead of changeLights. But even if you call it right, you create an interval with calling the same function each 1000 ms. That means at the second call, it create a new interval and calls it again and the actual interval call the function as well.
Solution: Separate initializing of the interval and the function for doing the work.
Start with startLights and call changeLights in the interval.
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index = index + 1;
if (index == list.length) {
index = 0;
}
console.log(index);
}
function startLights() {
setInterval(changeLights, 1000);
}
<button type="button" onclick="startLights()">Change Lights</button>
Error
changeLights() != ChangeLights()
Warning
Is the setInterval() placing
Not apply the setInterval() inside the click function.In each time loop time second's are reduced.so its change more lower time seconds.So use with setInterval with in click and color change was separate
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function change() {
index = index + 1;
if (index == list.length)
index = 0;
console.log(list[index])
}
function changeLights(){
var myVar = setInterval(function() {
change()
}, 1000);
}
<button type="button" onclick="changeLights()">Change Lights</button>
As above answers indicate - the call to the function needs to be outside it. One alteration I would suggest is to use the modulus operator (index % 3) which will allow a constant cycling of the images without the need for the if statement. This works because the modulus operator gives the remainder after dividing the number by the operator - so modulus %3 will mean that for example if index is three - the remainder is 0, 4 gives 1 5 gives 2 and then 6 is back at 0. So you have a perfect cycling count giving the three values 0,1, and 2 without having to check for each one.
var list = [
"https://assets.publishing.service.gov.uk/media/559fbe1940f0b6156700004d/traffic-light-red.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe48ed915d1592000048/traffic-light-amber.jpg",
"https://assets.publishing.service.gov.uk/media/559fbe3e40f0b6156700004f/traffic-light-green.jpg",
"http://thndl.com/images/1_3.png"
];
var index = 0;
function changeLights() {
index +=1;
document.getElementById('imageSrc').textContent = 'Source: ' + list[index %3];
document.getElementById('lights').src = list[index %3];
}
var myVar = setInterval(function() {
changeLights()
}, 1000);
<p id="imageSrc"></p>
<img id = "lights"/>

Increment counter then reset that counter when reached a certain limit

I have 18 images from which I only wish to show 5 at any given time. I'm swapping out a new image every two seconds or so without showing duplicates. My HTML is hardcoded and pulling from an s3 bucket.
<img class="activeImg" src="img_1.jpg />
<img src="img_2.jpg />
<img src="img_3.jpg />
<img src="img_4.jpg />
...
<img src="img_9.jpg />
I have a recursive setTimeout function that is calling moveCounter. moveCounter simply increments by 1, and replaces an image, every time it gets called. I hook into the element by adding the activeImg class to the img, then remove it before moving onto the next image.
The end goal is to count from 0...5, then back down 5...0, infinitely. All I'm doing is appending the value to an image name, thereby replacing images without showing a duplicate.
The problem is there is overlap and I'm getting a duplicate whenever counter === imgId.
// my recursive settimeout function fires off and adds an activeImg class to a random image element, then also fires off the replaceImage function
var counter = 0;
var imgId = 18;
// increment counter and append new img
function replaceImage(imgId){
if (counter >= 9) {
counter--;
var imgId = imgId - counter;
} else {
counter++;
var imgId = imgId - counter;
}
jQuery('.activeImg').attr('src', "image/img_"+imgId+".jpg");
console.debug(counter)
console.debug(imgId)
}
I feel like there is a better way to approach this.
Seems that what you're looking for is a simple triangle wave.
You can generate one rather easily:
var a = 5;
var output = [];
for (var i = 0; i < 20; i++) {
output.push(a - Math.abs(i % (2 * a) - a));
};
out.innerHTML = output;
<span id="out"></span>
var counter = 1;
var imgId = 18;
var op = 1; // the operation -- 1 for addition, -1 for subtraction
function replaceImage(imgId) {
// increment or decrement the counter, depending
// on the current direction
counter += op;
// use the original poster's snippet to set the active image
var imgId0 = imgId + counter;
$('.activeImg').attr('src', 'image/img_'+imgId0+'.jpg');
// if we hit the upper or lower bound, reverse the direction
// by flipping the operation
if (counter === 5 || counter === 1)
op *= -1;
}

How to start over again a loop?

I have a JSON file which stores an array of picture URLs. I want to rotate through these links, changing the background of a div every 4 seconds.
I'm having no trouble accessing the JSON file or changing the background of the div. However, I can't seem to figure out how to restart at the beginning of the array after every picture has been shown.
How should I approach this problem?
$.getJSON(json, function (data) {
var arr = $.map(data, function (el) { return el; })
, i = 0;
var changeObj = function() {
i++;
var url = 'url("' + arr[i].url + '")';
$this.css({
backgroundImage: url
});
};
setInterval(changeObj, 4000);
});
Here's a demo
Let's assume your have already parsed your JSON into an array of URLs called myPictureArray and you have written a function called swapInNewPicture, which takes a URL of an image as its argument. (I'm not going to write these functions for you.)
var rotatePictures = function (arr) {
var length = arr.length
, i = 0;
setInterval(function () {
i = (i + 1) % length;
swapInNewPicture(arr[i]);
}, 4000)
}
Now, all you have to do is call rotatePictures(myPictureArray) after you finish parsing your JSON.
Use the modulus operation so it wraps around when it reaches the end of the array. Replace:
i++;
with:
i = (i + 1) % arr.length;
This is basically equivalent to:
i++;
if (i == arr.length) {
i = 0;
}
BTW, you can simplify the setInterval call to:
setInterval(changeObj, 4000);

if counter reaches max count counter++ else counter = 0 in javascript

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.

Categories