I use JavaScript to change the background-image of a div dynamically every 4 seconds. my code looks like this:
const images = [
'img/landing-min.jpg',
'img/gallery-1.jpg',
'img/side-img.jpg',
];
window.onload = () => {
const landing = document.getElementById('landing');
landing.dataset.i = 0;
setInterval(() => {
landing.style.backgroundImage = `url(${images[landing.dataset.i]})`;
landing.dataset.i = (landing.dataset.i+1) % images.length;
}, 4000)
}
The problem is that the browser makes a request to get the file each time the interval changes the background image, which makes a lot of duplicate requests. I want all files to be requested only once.
Related
I have this code that clicks on the elements. The purpose of these buttons is to open accordions. It works but I need to modify it a little bit so as to reduce the load on the server. At the moment, all the buttons are clicked at once which causes some buttons on the same page not to work.
I was wondering if there is a way to wait for at least 3 seconds before clicking on the next button. All the buttons share the same class name.
const matchBtns = document.querySelectorAll('.classname')
matchBtns.forEach(matchbtn => matchbtn.click())
I have tried to wrap the forEach inside the setTimeout but I can't get it to work.
I tried
setTimeout(function() { matchBtns.forEach(matchbtn => matchbtn.click());}, 3000);
Thanks
You can change your implementation something like this
const matchBtns = document.querySelectorAll('.classname')
let nextClickIn = 0;
let delay = 3000;
matchbtns.forEach((matchbtn) => {
setTimeout(() => {matchbtn.click()}, nextClickIn)
nextClickIn += delay
})
Note: Provide the delay value in milliseconds
You can code this one as below:
const matchBtns = document.querySelectorAll('.classname')
let nextClick = 1;
let delay = 3000;
matchbtns.forEach((matchbtn) => {
setTimeout(() => {matchbtn.click()}, delay)
nextClick++;
delay *= nextClick
})
i know that there are question similar to this one, but my goal is different.
I have an array of Sceneobjects like this:
const scene = {
Id: Math.floor(Math.random() * 10000),
JsonObj: canvas.getJsonObj(),
image: this.editor?.export.toImage(),
duration: 1000,
};
And am using a library PikasoJS that alows me to export/import an image of a html div.
I put each image of div in scene object, and i want to display all these images in array scenes one by one automatically, and duration of scene is specified in duration field.
How can i implement something like this, i tried working with setInterval but it didn't work as i espected:
const playScene = () => {
const cpScenes = [...scenes];
let i = 0;
for(let i = 0;i < cpScenes.length;i++) {
setTimeout(() => {
let image = cpScenes[i].image;
console.log("am runnig");
this.editor.loadImage(image);
}, cpScenes[i].duration);
}
clearTimeout();
};
The way am thinking is that setTimeout should block execution of for loop and then executes it's code after specified time. But from what i noticed i was wrong.
This is my first time working with react and js.
I have an array containing a few values, each one of them is an image location on a website.
["img/image1.png", "img/image2.png", "img/image3.png", "img/image4.png"]
I need to loop through them and apply them as a src attribute to an image sequentially every second, image1 then image2, image3 and etc...
I Really want to use a for loop but I have compleately no idea where to start...
I don't think a for loop applies here because of the asynchronous nature of what you want.
Let's think about the behaviour:
# psuedocode
choose the next image
set image src
when the image has loaded
wait one second
loop from line #1
Implementing that logic
const images = ["https://via.placeholder.com/150", "https://via.placeholder.com/150x50", "https://via.placeholder.com/150x100", "https://via.placeholder.com/150x25"]
const image = document.querySelector('#image')
let currentImage = 0
function updateImage() {
// choose the next image
const newImageSrc = images[currentImage++ % images.length]
// set image src
image.src = newImageSrc
// when the image has loaded
image.onload = function () {
// wait one second (1000 milliseconds) and "loop"
setTimeout(updateImage, 1000)
}
}
// start with an image immediately without waiting
updateImage()
<img id="image">
Other answers here have used setInterval. It's my opinion that you should avoid setInterval as much as possible, and use a setTimeout with a self-referencing loop.
consider
function doSomethingIntesive() {
...
}
setInterval(doSomethingIntesive, 1000)
you want to call doSomethingIntensive every second. What happens if it takes more than 1 second to execute doSomethingIntensive? In your case, doSomethingIntensive would be "download the image and show it". Over slow connections, it's definitely possible for it to take more than 1 second.
now consider
function doSomethingIntensive() {
...
setTimeout(doSomethingIntensive, 1000)
}
setTimeout(doSomethingIntensive, 1000) // or just doSomethingIntensive() if you don't want the initial wait
This code with do the intensive operation in its entirety then queue a new invocation of the intensive function. You end up with much more consistent behaviour.
a nifty trick is to use a "virtual" image to download the image before applying it to the real dom element - taking advantage of browser caching.
const images = ["https://via.placeholder.com/150", "https://via.placeholder.com/150x50", "https://via.placeholder.com/150x100", "https://via.placeholder.com/150x25"]
const image = document.querySelector('#image')
let currentImage = 0
const vImage = new Image()
function updateImage() {
// choose the next image
const newImageSrc = images[currentImage++ % images.length]
vImage.onload = function() {
image.src = newImageSrc
/* this should be instant but it's still good
* practice to always use the onload event handler */
image.onload = function () {
setTimeout(updateImage, 1000)
}
}
vImage.src = newImageSrc
}
updateImage()
<img id="image">
open up your browser's dev tools and enable connection throttling. The first image might take a while to show up, but you'll never have an empty (no) image showing. ...although that might be beyond what you need for this.
You would want to use setTimeout, this will run a function in x milliseconds.
const images = ["https://via.placeholder.com/150", "https://via.placeholder.com/150x50", "https://via.placeholder.com/150x100", "https://via.placeholder.com/150x25"]
// Get the image reference
const img = document.querySelector('#my-image')
// Add an event to listen for when it loads and trigger the next change
img.onload = () => setTimeout(changeImage, 1000)
// A counter to count the times we change images
let counter = 0
function changeImage() {
// Set the image src
// We will get the modulus value
// Using this the number will never be larger than the length
img.src = images[counter++ % images.length]
}
changeImage()
<img id="my-image">
(added by geuis) Alternate setInterval example since the questioner may not have a high level understanding of js:
let counter = 0
setInterval(() => {
img.src = images[counter % images.length];
counter++;
}, 1000);
Currently, I have an array of images like this:
var images = [
"https://www.example.com/1.png",
"https://www.example.com/2.png",
"https://www.example.com/2.png"
];
So what is the best approach to handle the downloading process and also when all images download completed I need an event for that.
You can use fetch
which is a Promise
total = images.length
loaded = 0
progress = 0
progress = () => {
loaded += 1
progress = loaded / total
}
Promise.all(images.map(i => fetch(i).then(progress)))
.then(onComplete)
.catch(onError)
For downloading blob data refer to this question.
I'm trying to do what I 'thought' would be a simple task. I have an array of URLs that I'd like to loop through and download on to the client machine when the user clicks a button.
Right now I have a parent component that contains the button and an array of the urls (in the state) that I'd like to loop through and download. For some reason, the way I'm doing it now only downloads one of the files, not all of the contents of the array.
Any idea how to do this correctly within React?
handleDownload(event){
var downloadUrls = this.state.downloadUrls;
downloadUrls.forEach(function (value) {
console.log('yo '+value)
const response = {
file: value,
};
window.location.href = response.file;
})
}
I would use setTimeout to wait a little bit between downloading each files.
handleDownload(event){
var downloadUrls = this.state.downloadUrls.slice();
downloadUrls.forEach(function (value, idx) {
const response = {
file: value,
};
setTimeout(() => {
window.location.href = response.file;
}, idx * 100)
})
}
In Chrome, this will also prompt the permission asking for multiple files download.