create loop of moving images inside a div - javascript

I would like to build an image gallery like this where pictures keep looping automatically but at the same time, it's possible to interact through the gallery using the mouse wheel as well. I would also achieve an effect like that where images, instead of scrolling out of the screen shrink on the side.
So I was trying to understand where to start and I couldn't find any library for the task so I tried from scratch using vanilla js, this is my attempt.
var testArray = document.querySelectorAll(".image");
var totImg = testArray.length;
var contIterazioni = 0;
var test = testArray[contIterazioni];
var bounding = test.getBoundingClientRect();
function LoopFunction() {
setInterval(galleryScroll, 20);
}
function galleryScroll() {
test = testArray[contIterazioni];
bounding = test.getBoundingClientRect();
if (bounding.left == 0) {
//console.log("immagine bordo sx");
if (test.width > 0) {
test.width = test.width - .25;
} else {
contIterazioni = contIterazioni + 1;
if (contIterazioni >= totImg){
contIterazioni = 0;
}
}
}
}
LoopFunction();
body{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
overflow: hidden;
}
<div class="container">
<img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
<img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
<img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
<img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">
</div>
Unfortunately, I couldn't figure out how to loop the images. Can you help me understand how to do it? Do you think my approach can be a good one? or would you recommend other ways to get that effect?
Thanks!

Use for loop when you go through all images to set their width to their initial value. Also add extra three images from start of the carousel so there wouldn't be empty space when it comes to an end.
var testArray = document.querySelectorAll(".image");
var totImg = testArray.length;
var contIterazioni = 0;
var test = testArray[contIterazioni];
var bounding = test.getBoundingClientRect();
var imgsWidths = []
window.onload = () => {
for(i = 0; i < testArray.length; i++) {
imgsWidths[i] = testArray[i].width
}
}
function galleryScroll() {
test = testArray[contIterazioni];
bounding = test.getBoundingClientRect();
if (bounding.left == 0) {
if (test.width > 0) {
test.width = test.width - 2;
} else {
contIterazioni = contIterazioni + 1;
if (contIterazioni >= totImg - 3){
for(i = 0; i < testArray.length; i++) {
testArray[i].width = imgsWidths[i]
}
contIterazioni = 0;
}
}
}
window.requestAnimationFrame(galleryScroll)
}
window.requestAnimationFrame(galleryScroll);
body{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
overflow: hidden;
}
<div class="container">
<img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
<img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
<img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
<img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">
<img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
<img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
</div>

While keeping your same approach, this should work similarly as the example you provided. If you want the slideshow to keep it's width, all images should have the same width. Your error was not adding back the image that dissapeared to the container, at the end and with it's original width, or as in this case expanding again.
// From https://www.javascripttutorial.net/javascript-queue/
function Queue() {
this.elements = [];
}
Queue.prototype.enqueue = function(e) {
this.elements.push(e);
};
Queue.prototype.dequeue = function() {
return this.elements.shift();
};
Queue.prototype.isEmpty = function() {
return this.elements.length == 0;
};
Queue.prototype.peek = function() {
return !this.isEmpty() ? this.elements[0] : undefined;
};
Queue.prototype.length = function() {
return this.elements.length;
}
let images = new Queue();
document.querySelectorAll(".image").forEach(img => images.enqueue(img));
var totImg = images.length();
var first = images.dequeue();
var last;
var firstWidth = first.width;
var lastWidth = 0.0;
var bounding = first.getBoundingClientRect();
var originalWidth = first.width;
var lastOriginalWidth = 0.0;
var step = 1.0;
var lastStep = 0.0;
function LoopFunction() {
setInterval(galleryScroll, 20);
}
function galleryScroll() {
bounding = first.getBoundingClientRect();
if (bounding.left == 0) {
//console.log("immagine bordo sx");
if (first.width > 0) {
firstWidth -= step;
if (firstWidth < 0) {
firstWidth = 0;
}
first.style.width = firstWidth + 'px';
} else {
if (last && last.width != lastOriginalWidth) {
last.width = lastOriginalWidth;
}
let container = document.querySelector('.container');
container.removeChild(first);
last = first;
lastOriginalWidth = originalWidth;
last.width = 0.0;
lastWidth = 0.0;
images.enqueue(last);
container.appendChild(last);
first = images.dequeue();
originalWidth = first.width;
firstWidth = originalWidth;
lastStep = step * lastOriginalWidth / originalWidth;
}
}
if (last && last.width <= lastOriginalWidth) {
lastWidth += lastStep;
last.style.width = lastWidth + 'px';
if (last.width > lastOriginalWidth) {
last.width = lastOriginalWidth;
}
}
}
LoopFunction();
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
overflow: hidden;
}
<div class="container">
<img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
<img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
<img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
<img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">
</div>
Update #1
As requested by OP, here is some further explenation of the changes I made:
I used a simple queue from javascripttutorial to have a data structure that reflects the objective, i.e. having images that move from right to left, and once they "exit" the scene, can get enqueued again.
Following this concept, we need pointers to both head and tail of the queue in order to update their animation, in particular first, firstWidth and originalWidth are used respectively to point to the head, keep track of its current width during the animation and the originalWidth to which it should return when re-entering the scene. Similarly, this happens for the last as well.
Once this is in place, our loop will be made of two parts, one that handles the head animation and moves the images in the queue when the head image reaches width == 0 and one that handles the tail re-entering the scene and expanding. To achieve continuity, we use a simple proportion after we have our new queue: step : originalWidth = lastStep : lastOriginalWidth, which we use to determine at each frame how much respectively the head and tail images compress and expand. as step is a fixed parameter, lastStep is easily computed through simple arithmetics: lastStep = step * lastOriginalWidth / originalWidth.
The code:
let container = document.querySelector('.container');
container.removeChild(first);
last = first;
lastOriginalWidth = originalWidth;
last.width = 0.0;
lastWidth = 0.0;
images.enqueue(last);
container.appendChild(last);
first = images.dequeue();
originalWidth = first.width;
is just a contextual switch over the changing the queue, where the pointers and respective data get update to reflect the changes in the data structure. So the first becomes last, the next image in the queue is the new compressing first, as such originalWidth shifts.
Let's go further
Now, to achieve your desired implementation, this still needs some work. First of all, the queue should only reflect the actual carousel, not all the images you have, so ideally you would have a first static data structure with all the images and respective metadata, in this case we mainly need their original width. then you would have a queue representing the images that are being animated.
Now, you can either reuse this code and change the width of the images to be all equal and fit the viewport you are using for your animation, which should work fine. The other option is to mirror the code for the head image to the tail, have a fixed step, so while the head compresses of step pixels, the tail expands of the same step pixels, and when the tail reaches maximum width, introduce a new image at the end of the queue which becomes the new tail.
To go in further detail on the last, the algorithm would look something like this:
initialize static list of image containers with their respective width (imgList);
initialize an empty queue (imgQueue);
initialize a pointer pointing to the last image introduced in the queue (listPtr);
get the width of the viewport your carousel should fill (vpWidth);
while you have not filled such width, keep adding images to the queue and moving the listPtr left in the imgList;
have looping function similar to the one above but where the if over last replicates similar steps to the first ones;
This should be everything, I will work on the code in a while, now I need some sleep ;).
Update #2
Okay! Worked out something that actually works decently. If you have suggestions please let me know, in the meanwhile, here it is:
// From https://www.javascripttutorial.net/javascript-queue/
function Queue() {
this.elements = [];
}
Queue.prototype.enqueue = function(e) {
this.elements.push(e);
};
Queue.prototype.dequeue = function() {
return this.elements.shift();
};
Queue.prototype.isEmpty = function() {
return this.elements.length == 0;
};
Queue.prototype.first = function() {
return !this.isEmpty() ? this.elements[0] : undefined;
};
Queue.prototype.length = function() {
return this.elements.length;
};
// Added function to peek last element in queue
Queue.prototype.last = function() {
return !this.isEmpty() ? this.elements[this.elements.length - 1] : undefined;
};
// Added function that pops the head, enqueues it and returns it
Queue.prototype.shift = function() {
const head = this.dequeue();
this.enqueue(head);
return head;
}
// Returns a queue of HTMLElements based on the given class
function loadQueue(className) {
const rQueue = new Queue();
document.querySelectorAll('.' + className).forEach(image => rQueue.enqueue(image));
return rQueue;
}
// Queue of images to be added to the animation queue
const imgQueue = loadQueue('image');
// Images being animated inside the div
const imgAnimQueue = new Queue();
// To limit calls to the carousel
const carousel = $('.container');
function init() {
// Width of the viewport being used for the animation
// TODO: this shoud update whenever the page is resized, or at least the div
const vpWidth = carousel.width();
// Keeps track of the width of the images added to the animation queue
var currentFilledWidth = 0;
// Now that we have loaded the static information, let's clear the div
// that will be used as carousel, so that we can add the correct number
// of images back in
carousel.empty();
// Filling the animation queue
while (currentFilledWidth < vpWidth) {
// In order not to change the static data, we clone the image HTMLElement
const img = $(imgQueue.shift()).clone();
// Enqueuing the new image in the animation queue
imgAnimQueue.enqueue(img);
// Adding this image into the carousel
img.appendTo(carousel);
currentFilledWidth = currentFilledWidth + img.width();
// If we overflow the carousel width, we set the tail image to fill
if (currentFilledWidth > vpWidth) {
const overflow = currentFilledWidth - vpWidth;
img.width(img.width() - overflow);
currentFilledWidth -= overflow;
}
}
const step = 1;
var firstWidth = imgAnimQueue.first().width();
var lastWidth = imgAnimQueue.last().width();
// Now the loop can start
window.requestAnimationFrame(animateCarousel);
// Main function that animates the carousel
function animateCarousel() {
let first = imgAnimQueue.first();
let last = imgAnimQueue.last();
// If the image is still not disappeared, keep compressing it
if (firstWidth > 0) {
firstWidth -= step;
if (firstWidth < 0) firstWidth = 0;
first.width(firstWidth);
// Otherwise, remove it from the carousel and update all the data structs
} else {
first.remove();
imgAnimQueue.dequeue();
if (imgAnimQueue.first() != last) {
first = imgAnimQueue.first();
firstWidth = first.width();
} else {
first = last;
firstWidth = lastWidth;
imgAnimQueue.enqueue($(imgQueue.shift()).clone());
last = imgAnimQueue.last();
lastWidth = last.width();
last.appendTo(carousel);
}
}
if (lastWidth <= last.attr("data-original-width")) {
lastWidth += step;
// The image has completely expanded, let's introduce the next one
if (lastWidth >= last.attr("data-original-width")) {
last.width(last.attr("data-original-width"));
imgAnimQueue.enqueue($(imgQueue.shift()).clone());
last = imgAnimQueue.last();
last.width(0);
lastWidth = last.width();
last.appendTo(carousel);
// Otherwise just keep expanding it
} else {
last.width(lastWidth);
}
}
window.requestAnimationFrame(animateCarousel);
}
}
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var loadedImages = 0;
const count = 4;
function loadImage(img) {
if (loadedImages != count) {
$(img).attr("data-original-width", $(img).width());
loadedImages += 1;
if (loadedImages == count) init();
}
}
</script>
<div class="container">
<img onload="loadImage(this)" src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="1" class="image">
<img onload="loadImage(this)" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="2" class="image">
<img onload="loadImage(this)" src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="3" class="image">
<img onload="loadImage(this)" src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="4" class="image">
</div>

Related

Image not moving onclick

I'm trying make this image move 16px every click, but it's not moving. I've tried this:
But that only moves it once. So I tried something different that I found online.
Here is my code:
Html:
document.getElementById('player').style.left += "-16px";
function left() {
var left = parseInt(player.style.left);
player.style.left = (left +16) + "px";
}
<img id="player" src="characters/prisoner-down.png"></img>
<img id="leftbtn" src="icons/left.png" onclick="left();"></img>
Edit: if it's useful to know, there are gonna be three more buttons for the other directions and the image I want to move is in another DIV from the image that moves it. On my editor it says that the symbol ` is invalid, so I'd like to avoid it.
You can create a function that get the direction of the translation and the number of pixels to increment, then return a function that set style.transform of the element clicked, using a closure you can update the amount of pixels to translate, try this:
function transform(side, n) {
let translatePixels = 0;
if (side == 'right') {
return function(e) {
translatePixels += n;
e.target.style.transform = `translate(${translatePixels}px)`;
}
}
if (side == 'left') {
return function(e) {
translatePixels -= n;
e.target.style.transform = `translate(${translatePixels}px)`;
}
}
}
const translateRight = transform('right', 16);
const translateLeft = transform('left', 16);
<img onclick="translateRight(event);" src="https://images.rappi.com.ar/products/2311265-1622567743906.png?d=200x200&e=webp"></img>
<img onclick="translateLeft(event);" src="https://cdn.domestika.org/c_fill,dpr_auto,f_auto,h_256,pg_1,t_base_params,w_256/v1499705651/avatars/000/536/178/536178-original.jpg?1499705651" style="right: 0; position:absolute"></img>
Give position property to the img which you want to move.
Like position: relative;, position: absolute; etc.
By positioning them you can use top, left, right and top properties.
don't use position: static; on that img cause above property has no effect on static element.
document.getElementById('player').style.left = "-16px";
function left() {
let left = parseInt(player.style.left);
player.style.left = `${parseInt(left+16)}px`;
}
img{
/*important for using left, right, top and bottom properties*/
position: relative;
}
<img id="player" src="https://i.postimg.cc/44pXvSwD/pngwing-com.png"></img>
<img id="leftbtn" src="https://i.postimg.cc/FRkMDYvr/Pngtree-right-arrow-flat-multi-color-3777297.png" onclick="left();"></img>

How to use the counter when the counter appears on the page and not when the page is loaded

In my project, there should be a counter.
I want the counter to start when scrolling is done, not when the screen is loading.
I used "reveal" for this, but still the counter starts when the screen loads.
In the project in question, I like when scrolling the page from top to bottom and from bottom to top "reveal" arrives, the counter starts.
How can I solve this problem? Thanks in advance for your guidance.
//counter
const counter = (EL) => {
const duration = 4000; // Animate all counters equally for a better UX
const start = parseInt(EL.textContent, 10); // Get start and end values
const end = parseInt(EL.dataset.counter, 10); // PS: Use always the radix 10!
if (start === end) return; // If equal values, stop here.
const range = end - start; // Get the range
let curr = start; // Set current at start position
const loop = (raf) => {
if (raf > duration) raf = duration; // Stop the loop
const frac = raf / duration; // Get the time fraction
const step = frac * range; // Calculate the value step
curr = start + step; // Increment or Decrement current value
EL.textContent = parseInt(curr, 10); // Apply to UI as integer
if (raf < duration) requestAnimationFrame(loop); // Loop
};
requestAnimationFrame(loop); // Start the loop!
};
document.querySelectorAll("[data-counter]").forEach(counter);
//counter
// reveal
function reveal() {
var reveals = document.querySelectorAll(".reveal");
for (var i = 0; i < reveals.length; i++) {
var windowHeight = window.innerHeight;
var elementTop = reveals[i].getBoundingClientRect().top;
var elementVisible = 10;
if (elementTop < windowHeight - elementVisible) {
reveals[i].classList.add("active");
} else {
reveals[i].classList.remove("active");
}
}
}
window.addEventListener("scroll", reveal);
// reveal
.container{
overflow-y: scroll;
}
.pre-reveal{
width: 100%;
height: 80vh;
border: 1px solid red;
}
/* reveal */
.reveal {
border: 1px solid green;
position: relative;
opacity: 0;
margin-top: 1rem;
}
.reveal.active {
opacity: 1;
}
/* reveal */
<div class="container">
<div class="pre-reveal"></div>
<div class="reveal">
<span>A: </span>
<span data-counter="10">0</span>
<br>
<span>B: </span>
<span data-counter="2022">1000</span>
<br>
<span>C: </span>
<span data-counter="0">9999</span>
<br>
<span>D: </span>
<span data-counter="-1000">1000</span>
<br>
<span>E: </span>
<span data-counter="666">0</span>
<br>
</div>
</div>

loop through array to create image slider with vanilla javascript

I am trying to create an image carousel and I want the images to loop through the array. The code is clearly working because the "no click" alert shows but I don't understand what I am doing wrong.
Here is JS. I know the problem is most likely the if statement. I'm a beginner in JS and haven't quite understood how to code that bit properly. In some sort of pseudo code, it would ideally be "if btn is clicked, then show the next image".
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
let img = images.length;
let x = 0;
function whenClicked(e) {
for (let i = 0; i < img; i++) {
if (x == 0) {
document.getElementById("img1").style.backgroundImage = ++img;
} else alert("no click!")
}
}
const btnLeft = document.getElementById("btn-left");
const btnRight = document.getElementById("btn-right");
btnLeft.addEventListener("click", whenClicked);
btnRight.addEventListener("click", whenClicked);
And here HTML.
<div class="slide-container">
<div class="slide" id="img1">
<i class="fas fa-arrow-circle-left fa-3x" id="btn-left" ></i>
<i class="fas fa-arrow-circle-right fa-3x" id="btn-right" ></i>
</div>
</div>
CSS.
.slide-container {
}
.slide {
height: 789px;
width: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.slide:nth-child(1) {
background-image: url(../img/img1.jpg);
}
.slide:nth-child(2) {
background-image: url(../img/img2.jpg);
}
.slide:nth-child(3) {
background-image: url(../img/img3.jpg);
}
#btn-left {
position: absolute;
top: 400px;
}
#btn-right {
position: absolute;
left: 1380px;
top: 400px;
}
Suggestions on what to do to improve would be deeply appreciated!
You might be overcomplicating your approach. Try to keep track of which image is currently being shown and what image should be next. You are almost doing this, with I assume is your intent, with the x variable. This is a great way to select an image from the array by simply doing images[x], which translates to images[0] at the start.
So if you want to develop a system which changes the background image of the slide, then your buttons would have to change the value of the x variable. Let's give that variable a more clear name, like currentIndex which represents the current index in the images array. Or to be clear, the current image we are seeing.
When your right button is clicked, you'll want the next image. The next images in the images array is images[1]. All you have to do is update the currentImage value with +1 or ++ and select the next image with images[currentIndex] to get the next one.
Same goes for the left button which should remove 1 from the currentImage with either -1 or -- to go back one index in the images array. Then select the image the same way with images[currentIndex].
Now for both these buttons you'll need to check if you go past the start or the end of the images array. currentIndex cannot be lower than 0 and with 3 images in the array, the currentIndex value should not be higher than 2, since we are counting with [0, 1, 2] in the images array.
Below I've made an implementation of this system. I hope this is what you intended to make. If I haven't been clear or you have question, then don't hesitate to ask.
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
let amountOfImages = images.length;
let currentIndex = 0;
const slide = document.getElementById("img1");
const btnLeft = document.getElementById("btn-left");
const btnRight = document.getElementById("btn-right");
function prevImage() {
if (currentIndex > 0) { // Can't go lower than 0.
currentIndex--;
updateImage();
}
}
function nextImage() {
if (currentIndex < amountOfImages - 1) { // Can't go higher than the amount of images present.
currentIndex++;
updateImage();
}
}
function updateImage() {
slide.style.backgroundImage = images[currentIndex];
}
btnLeft.addEventListener("click", prevImage);
btnRight.addEventListener("click", nextImage);
let currentImage = 0;
let images = ["img1.jpg", "img2.jpg", "img3.jpg"];
function whenClicked(e) {
if(e.target.id == 'btn-left') {
currentImage--;
} else {
currentImage++;
}
if(currentImage > images.length-1) {
currentImage = 0;
}
if(currentImage < 0) {
currentImage = images.length-1;
}
document.getElementById("img1").style.backgroundImage = url('img/'+images[currentImage]);
}

I am creating an image slider and when the image is set back to the other side of the screen it wont continue moving

So my idea was that i move 4 images by 150px per click to the left and when an image reaches the end of the screen it gets to the other side so it could repeat the circle. But once the image actually gets on the right side of the screen it stops moving on click.
My Code
`// VARIABLE FOR THE MENU SLIDER
var move = 150;
// MEAL ITEM SLIDER IMAGES
var imgFood1 = document.getElementById('imgFood1')
var imgFood2 = document.getElementById('imgFood2')
var imgFood3 = document.getElementById('imgFood3')
var imgFood4 = document.getElementById('imgFood4')
imgFood1.style.position = "relative"
imgFood2.style.position = "relative"
imgFood3.style.position = "relative"
imgFood4.style.position = "relative"
function menuSlider(){
// GETTING THE POSITION OF THE IMAGES
var positionImg1 = imgFood1.getBoundingClientRect();
var positionImg2 = imgFood2.getBoundingClientRect();
var positionImg3 = imgFood3.getBoundingClientRect();
var positionImg4 = imgFood4.getBoundingClientRect();
// MOVING THE IMAGES
imgFood1.style.right=move+"px"
imgFood2.style.right=move+"px"
imgFood3.style.right=move+"px"
if(positionImg4.left > 0 ) {
imgFood4.style.right=move+"px"
}else {
imgFood4.style.left="500px"
}
// INCREMENTING THE MOVE VALUE FOR THE NEXT FUNCTION CALL
move+=150
}
button.addEventListener("click", menuSlider);
`
You can try the code bellow. Hope it fits your case.
var move = 150;
// MEAL ITEM SLIDER IMAGES
var imgFood1 = document.getElementById('imgFood1')
var imgFood2 = document.getElementById('imgFood2')
var imgFood3 = document.getElementById('imgFood3')
var imgFood4 = document.getElementById('imgFood4')
imgFood1.style.position = "absolute"
imgFood1.style.left = 0;
imgFood2.style.position = "absolute"
imgFood2.style.left = '150px';
imgFood3.style.position = "absolute"
imgFood3.style.left = '300px';
imgFood4.style.position = "absolute"
imgFood4.style.left = '450px';
function menuSlider(){
var arrayOfImages = [imgFood1,imgFood2,imgFood3,imgFood4];
for(let i = 0; i < arrayOfImages.length; i++) {
var positionImg = arrayOfImages[i].getBoundingClientRect();
var leftValue = parseInt(arrayOfImages[i].style.left);
if(positionImg.x < window.innerWidth) {
arrayOfImages[i].style.left = leftValue + move + "px"
}else {
arrayOfImages[i].style.left = '0px'
}
}
}
document.getElementById('myButton').addEventListener("click", menuSlider);
#myButton {
position: absolute;
top: 160px;
}
.images-container {
position: relative;
width: 100%;
height: 150px;
overflow: hidden;
}
<div class="images-container">
<img id="imgFood1" src="https://i.imgur.com/30XsebB.jpg" alt="cat" height="150" width="150"/>
<img id="imgFood2" src="https://i.imgur.com/30XsebB.jpg" alt="cat" height="150" width="150"/>
<img id="imgFood3" src="https://i.imgur.com/30XsebB.jpg" alt="cat" height="150" width="150"/>
<img id="imgFood4" src="https://i.imgur.com/30XsebB.jpg" alt="cat" height="150" width="150"/>
</div>
<button id="myButton" type="button" class="btn btn-default" data-dismiss="modal">Scroll</button>

Javascript recursion problem

I am trying to write a function that will change between an array of images. What I have makes sense to me, but when I run it as it is below then the first image loads, then the second image loads at some point (the transparency doesn't change) and then nothing happens. Here is the javascript code:
var image1 = new Image();var image2 = new Image(); var image3 = new Image();
image1.src = "images/website6.jpg"; image2.src = "images/website7.jpg"; image3.src = "images/sunset.jpg";
var images = new Array("images/website6.jpg","images/website7.jpg","images/sunset.jpg");
/*document.slide.style.opacity = 1;
document.slide.stylebg.opacity = 0;*/
setTimeout(function() { fade(images,0); }, 2000);
function delay(arr,num)
{
document.slide.src = arr[num % 3];
document.slide.style.opacity = 1;
document.slidebg.style.opacity = 0;
document.slidebg.src = arr[(num+1)%3];
var number = num + 1;
setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr,num)
{
/*alert('fadebefore ' + (document.slide.style.opacity).toString())*/
document.slide.style.opacity -= 0.1
/*alert('fade')*/
document.slide.stylebg.opacity += 0.1
if (document.slide.style.opacity == 0)
{
setTimeout(function() { delay(arr,num); }, 150);
}
else
{
setTimeout(function() { fade(arr,num); }, 1500);
}
}
The HTML is simple. I have two classes; style and stylebg. style sits in front of stylebg and then I change opacities and images as needed. The javascript seems logical to me, but it doesn't work as expected. Also worth noting is there are 3 comments. The first comment (line 3-4) is attemping to set the opacities to what they should be at the beginning. However, if I do this then I get even less progress than above: the first image loads and nothing else happens. The second two comments are used for debugging purposes. If I uncomment these then the image change occurs between the two alerts, which would seem to say the image change is caused by the opacity change.
So can anybody explain why it isn't doing what I expect it to? Thanks.
EDIT: Some more code:
HTML (This is the only part being affected):
<div style="position: relative;">
<img src="images/sunset.jpg" id="slide" />
<img src="images/website6.jpg" id="slidebg" />
</div>
CSS:
#slide{
display:block;
margin-left:5;
margin-right:auto;
border: 1px solid black;
z-index: 1;
top: 0px;
position: relative;
}
#slidebg{
display:block;
margin-left:auto;
margin-right:auto;
border: 1px solid black;
z-index: 0;
top: 0px;
position: absolute;
}
Answering for formatting's sake. I have not debugged to see what would work, but this makes more sense to me
If you want to use ID, use document.getElementById, if you want to use name, use document.images[imgname] or document.imagename
You are mixing names and style too. document.slide.stylebg.opacity and such
This does something. Not sure it is what you want: http://jsfiddle.net/EcShW/2/
<div style="position: relative;">
<img src="images/sunset.jpg" id="slide" name="slide" />
<img src="images/website6.jpg" id="slidebg" name="slidebg" />
</div>
var images = []; // can be more elegant, but this is simpler
images[0]=new Image(); images[0].src="images/website6.jpg";
images[1]=new Image(); images[1].src="images/website7.jpg";
images[2]=new Image(); images[2].src="images/sunset.jpg";
var tid1,tid2,tid3
tid1=setTimeout(function() { fade(images,0); }, 2000);
function delay(arr,num)
{
document.slide.src = arr[num % 3].src;
document.slide.style.opacity = 1;
document.slidebg.style.opacity = 0;
document.slidebg.src = arr[(num+1)%3].src;
var number = num + 1;
tid2=setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr,num)
{
document.slide.style.opacity -= 0.1
document.stylebg.style.opacity += 0.1
if (document.slide.style.opacity == 0)
{
tid3=setTimeout(function() { delay(arr,num); }, 150);
}
else
{
tid3=setTimeout(function() { fade(arr,num); }, 1500);
}
}
You can't just refer to page elements by "id" value like that; you have to use "document.getElementById()":
var slideElement = document.getElementById('slide'), slidebgElement = document.getElementById('slidebg');
Then you'd work with "slideElement.style" etc. instead of "document.slide.style".
EDIT2
It works for me (chromium)
var images = new Array ();
images[0] = new Image();
images[0].src = "images/website6.jpg";
images[1] = new Image();
images[1].src = "images/website7.jpg";
images[2] = new Image();
images[2].src = "images/sunset.jpg";
function delay ( arr, num )
{
slide.src = arr[num % 3].src;
slide.style.opacity = 1;
slidebg.style.opacity = 0;
slidebg.src = arr[(num+1)%3].src;
var number = num + 1;
setTimeout(function() { fade(arr,number); }, 2000);
}
function fade(arr, num)
{
if ( slide.style.opacity == 0 )
setTimeout(function (){ delay(arr, num); }, 150);
else
{
slide.style.opacity = (slide.style.opacity*10 - 1)/10 ;
slidebg.style.opacity -= -0.1;
setTimeout ( function(){fade(arr,num);}, 1500 );
}
}
fade (images, 0);
AHA!
<img id="img_id"/> we can get by document.img_id, even in chromium
OK, OK, removed links to this WE TEACH YOU TO FAIL AT WEB DEV site..

Categories

Resources