To continue on the question here. Since I am doing this for the first time, and I still consider myself a newbie in javascript I would like to know how to properly preload images for the browser.
This is my script:
$(document).ready(function () {
var imagesIndex = 0;
var loadedImages = new Array();
var nextImage = 0;
preload();
function preload() {
for (i = 0; i < 2; i++) {
if (nextImage < images.length) {
var img = new Image();
img.src = '/imagecache/cover/' + images[nextImage];
loadedImages[nextImage] = img;
++nextImage;
}
}
}
$('#forward').click(function() {
imagesIndex++;
preload();
if (imagesIndex > (loadedImages.length - 1)) {
imagesIndex = 0;
}
$('#image').attr({"src" : '/imagecache/cover/' + loadedImages[imagesIndex], "alt" : name});
});
$('#back').click(function() {
imagesIndex--;
if (imagesIndex < 0) {
imagesIndex = (loadedImages.length - 1);
}
$('#image').attr({"src" : '/imagecache/cover/' + loadedImages[imagesIndex], "alt" : name});
});
});
I am getting images from the global array images, and then using preload function to preload 2 at the time. I wonder what do I need to send as a source to the image element. Is that a src from the loadedImages array element or from the images array?
Related
I have been playing with this code for a while and I was wondering why when I try to add img’s to the array on the js code makes the images appear on DOM but also makes a bunch of Undefined elements appear, How can I just make the 15 images appear without the undefined? Thanks
enter link description here
var previous = document.getElementById('btnPrevious')
var next = document.getElementById('btnNext')
var gallery = document.getElementById('image-gallery')
var pageIndicator = document.getElementById('page')
var galleryDots = document.getElementById('gallery-dots');
var images = ["https://exoplanets.nasa.gov/internal_resources/1763/",
"https://cdn.britannica.com/56/234056-050-0AC049D7/first-image-from-James-Webb-Space-Telescope-deepest-and-sharpest-infrared-image-of-distant-universe-to-date-SMACS-0723.jpg",
"https://assets.newatlas.com/dims4/default/ac389ce/2147483647/strip/true/crop/1620x1080+150+0/resize/1200x800!/quality/90/?url=http%3A%2F%2Fnewatlas-brightspot.s3.amazonaws.com%2Farchive%2Funiverse-expanding-acceleration-1.jpg",
"https://media.newyorker.com/photos/590966ee1c7a8e33fb38d6cc/master/w_2560%2Cc_limit/Nissan-Universe-Shouts.jpg",
"https://www.thoughtco.com/thmb/NY5k_3slMRttvtS7mA0SXm2WW9Q=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/smallerAndromeda-56a8ccf15f9b58b7d0f544fa.jpg",
"https://static.scientificamerican.com/sciam/cache/file/05B8482C-0C04-4E41-859DCCED721883D2_source.jpg?w=590&h=800&7ADE2895-F6E3-4DF4-A11F51B652E9FA88",
"https://qph.cf2.quoracdn.net/main-thumb-66277237-200-huqebnzwetdsnnwvysbxemlskpcxnygf.jpeg",
"http://www.pioneertv.com/media/1090/hero_shot_1080x720.jpg?anchor=center&mode=crop&width=600&height=400&rnd=133159257140000000",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSWFW1EpMNFM5-dbZEUUnzJkzT3KbUCeuhPHx_eseFCpPeX4Q_DIVPopjS0LeKVmKdQho&usqp=CAU",
"https://cdn.mos.cms.futurecdn.net/rwow8CCG3C3GrqHGiK8qcJ.jpg",
"https://static.wixstatic.com/media/917d103965314e2eacefed92edb6492c.jpg/v1/fill/w_640,h_356,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/917d103965314e2eacefed92edb6492c.jpg",
"https://astronomy.com/~/media/A5B9B6CF36484AB9A6FFAE136C55B355.jpg",
"https://discovery.sndimg.com/content/dam/images/discovery/fullset/2022/9/alien%20planet%20GettyImages-913058614.jpg.rend.hgtvcom.616.411.suffix/1664497398007.jpeg",
"https://images.newscientist.com/wp-content/uploads/2017/06/21180000/planet-10-orange-blue-final-small.jpg?crop=16:9,smart&width=1200&height=675&upscale=true",
"https://images.hindustantimes.com/img/2022/07/20/1600x900/Viral_Instagram_Planet_Rainbow_Nasa_1658316556293_1658316573815_1658316573815.PNG"
]
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: images[i]
});
}
var perPage = 8;
var page = 1;
var pages = Math.ceil(images.length / perPage)
// Gallery dots
for (var i = 0; i < pages; i++){
var dot = document.createElement('button')
var dotSpan = document.createElement('span')
var dotNumber = document.createTextNode(i + 1)
dot.classList.add('gallery-dot');
dot.setAttribute('data-index', i);
dotSpan.classList.add('sr-only');
dotSpan.appendChild(dotNumber);
dot.appendChild(dotSpan)
dot.addEventListener('click', function(e) {
var self = e.target
goToPage(self.getAttribute('data-index'))
})
galleryDots.appendChild(dot)
}
// Previous Button
previous.addEventListener('click', function() {
if (page === 1) {
page = 1;
} else {
page--;
showImages();
}
})
// Next Button
next.addEventListener('click', function() {
if (page < pages) {
page++;
showImages();
}
})
// Jump to page
function goToPage(index) {
index = parseInt(index);
page = index + 1;
showImages();
}
// Load images
function showImages() {
while(gallery.firstChild) gallery.removeChild(gallery.firstChild)
var offset = (page - 1) * perPage;
var dots = document.querySelectorAll('.gallery-dot');
for (var i = 0; i < dots.length; i++){
dots[i].classList.remove('active');
}
dots[page - 1].classList.add('active');
for (var i = offset; i < offset + perPage; i++) {
if ( images[i] ) {
var template = document.createElement('div');
var title = document.createElement('p');
var titleText = document.createTextNode(images[i].title);
var img = document.createElement('img');
template.classList.add('template')
img.setAttribute("src", images[i].source);
img.setAttribute('alt', images[i].title);
title.appendChild(titleText);
template.appendChild(img);
template.appendChild(title);
gallery.appendChild(template);
}
}
// Animate images
var galleryItems = document.querySelectorAll('.template')
for (var i = 0; i < galleryItems.length; i++) {
var onAnimateItemIn = animateItemIn(i);
setTimeout(onAnimateItemIn, i * 100);
}
function animateItemIn(i) {
var item = galleryItems[i];
return function() {
item.classList.add('animate');
}
}
// Update page indicator
pageIndicator.textContent = "Page " + page + " of " + pages;
}
showImages();
I checked your code and make it work with a small modification.
You are reusing the same array with the links of images and push inside the new object with the shape of { title, source }.
You just need to do this changes:
Change the name of your array of images. Something from images to arrayOfImages.
const arrayOfImages = ["https://exoplanets.nasa.gov/internal_resources/1763/", ...]
Declare an empty array before your first for loop. Make something like const images = []
On your for loop, instead of loop over the images variable, do it over the arrayOfImages variable.
const images = [];
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: arrayOfImages[i]
});
}
With those changes, everything works for me.
Also, as a recommendation, try to avoid the var keyword. If you want more details about this, this answer is very helpful: https://stackoverflow.com/a/50335579/17101307
You can use Array#map to create a new array of objects from the array of URLS, then replace the original array.
images = images.map((x, i) => ({
title: "Image " + (i + 1),
source: x
}));
I have quite a few static photos on my page. My goal is to show a loader while the page and the image loads. The problem is after my loader disappears, the image is not fully rendered yet.
How can I make the loader disappear after the images fully rendered?
Here is my current attempt from a different source.
Javascript:
(function(){
function id(v){return document.getElementById(v); }
function loadbar() {
var ovrl = id("overlay"),
prog = id("progress"),
stat = id("progstat"),
img = document.images,
c = 0;
tot = img.length;
function imgLoaded(){
c += 1;
var perc = ((100/tot*c) << 0) +"%";
prog.style.width = perc;
stat.innerHTML = "Loading "+ perc;
if(c===tot) return doneLoading();
}
function doneLoading(){
ovrl.style.opacity = 0;
setTimeout(function(){
ovrl.style.display = "none";
}, 1200);
}
for(var i=0; i<tot; i++) {
var tImg = new Image();
tImg.onload = imgLoaded;
tImg.onerror = imgLoaded;
tImg.src = img[i].src;
}
}document.addEventListener('DOMContentLoaded', loadbar, false);}());
You're missing the image in the body
...
function doneLoading(){
ovrl.style.opacity = 0;
setTimeout(function(){
ovrl.style.display = "none";
}, 1200);
//you should put
document.body.appendChild(this);
}
...
I need your help. My script validate images resolution before sending form.
The problem is that when script should stop because one or more photos is bigger than maximum resolution. It's not happening.
var err is counting number of bad resolution photos, but on the end, i dont know why it is always 0.
Any ideas?
jQuery("form").submit( function( e ) {
var form = this;
e.preventDefault();
var photos = document.getElementById('imgInp');
var howmany = photos.files.length;
var err = 0;
var img = new Array();
for (var i = 0; i < howmany; i++) {
if (photos.files[i]) {
img[i] = new Image();
img[i].src = window.URL.createObjectURL( photos.files[i] );
img[i].onload = function() {
window.URL.revokeObjectURL( this.src );
if( this.width < 1281 && this.height < 1025 ) {
} else {
alert('Zdjęcie jest zbyt duże');
err++;
}
};
} else {
form.submit();
}
}
if(err > 0) {
alert('Niestety ale jedno lub więcej zdjęć, które próbujesz załadować są zbyt duże (dopuszczalna rozdzielczość maksymalna to 1280 x 1024).');
} else {
alert('Ok'); // form.submit();
}
});
https://jsfiddle.net/5fv42o0e/2/
It's because
Image loading is asynchronous
Image loading takes time but browser won't pause your script it would keep running code that follows.For simplicity keeping aside your code assume I have this
var img = new Image();
img.onload = function(){ alert('image loaded');}
img.src = "lion.jpg";
alert('hello');
Because loading image will always take some finite time you would always see "hello" being alerted before "image loaded" always!
Now you can probably guess where the problem was , when your forloop was over completing all its iteration not even the first image is done loading up till that time so err is 0 therefore no error message.
How to solve?
You can choose from a variety of solutions - callbacks,promise,counters etc.Assuming it's a simple application below I have used counters to solve
<script>
var err = 0;
var counter = 0;
jQuery("form").submit( function( e ) {
var form = this;
e.preventDefault();
var photos = document.getElementById('imgInp');
var howmany = photos.files.length;
var img = new Array();
for (var i = 0; i < howmany; i++) {
if (photos.files[i]) {
img[i] = new Image();
img[i].src = window.URL.createObjectURL( photos.files[i] );
counter++;
img[i].onload = function() {
window.URL.revokeObjectURL( this.src );
if( this.width < 1281 && this.height < 1025)
{
} else {
alert('Zdjecie jest zbyt duze');
err++;
}
counter--;
if(counter === 0 ){
if(err > 0) {
alert('Niestety ale jedno lub wiecej zdjec, które próbujesz zaladowac sa zbyt duze (dopuszczalna rozdzielczosc maksymalna to 1280 x 1024).');
} else {
alert('Ok'); // form.submit();
}
}
};
}
}
});
</script>
Here is how it works : A counter will keep track of how many images are outstanding ie. for which src has been assigned but are waiting to get loaded.Increment counter each time you assign a src and decrement it each time an image gets loaded (onload function) also check if it was the last image to get loaded (check if counter is 0) if yes all images are done now run your check
I'm using JavaScript to randomly display an array of images with timed intervals.
This is the script:
var NumberOfImages = 5
var img = new Array(NumberOfImages)
img[0] = "[image here]"
img[1] = "[image here]"
img[2] = "[image here]"
img[3] = "[image here]"
img[4] = "[image here]"
Array.prototype.shuffle = function () {
var len = this.length;
var i = len;
while (i--) {
var p = parseInt(Math.random()*len);
var t = this[i];
this[i] = this[p];
this[p] = t;
}
};
img.shuffle ();
var imgNumber = 0
function NextImage() {
document.images["VCRImage"].src = img[imgNumber++]
if (imgNumber == img.length) {
img.shuffle ();
imgNumber = 0;
}
}
window.setInterval (NextImage, 3000);
and the html:
<div class="item">
<script type="text/javascript">document.writeln('<img src="'+img[0]+'" name="VCRImage">');</script>
</div>
A working example can be found here: https://jsfiddle.net/admiringtheorchid/esm3u0xg/
I would like to ease the transition between each image. How can this be accomplished?
Try this method with jQuery: https://jsfiddle.net/joe_young/qxf69hsL/
//create a jQuery object of the image
var $image = $(document.images["VCRImage"]);
//fade out the image, and once it has finished fading out...
$image.fadeOut(function() {
//change the image source
$image.attr("src", img[imgNumber++]);
});
//fade the image back in
$image.fadeIn();
I want to draw image array with drawImage after all the images are loaded.There is a render problem with drawImage(), tried to solve with setTimeout() but its not working all the time.
Here is my code;
while(FocusItem.length>0)
{
FocusItem.pop();
}
ftx=canvas.getContext('2d');
focusImageBackground = new Image();
focusImageBackground.src = "./images/odaklanma/odaklanmaBackground.jpg";
if(RandomSoru==15)
finishSoru=true;
if(finishSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
tempRandomSoru=RandomSoru;
}
if(RandomSoru==tempRandomSoru)
{
RandomSoru = Math.floor((Math.random() * 15)+1);
}
var soru = new Object();
soru["image"] = new Image();
soru.image.src = './images/odaklanma/level/'+RandomSoru+'/soru.png';
soru["x"] = 341;
soru["y"] = 140;
FocusItem.push(soru);
var dogru = new Object();
dogru["image"] = new Image();
dogru.image.src = './images/odaklanma/level/'+RandomSoru+'/dogru.png';
dogru["x"] = xDogru;
dogru["y"] = 280;
FocusItem.push(dogru);
var yanlis = new Object();
yanlis["image"] = new Image();
yanlis.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis.png';
yanlis["x"] = xYanlis1;
yanlis["y"] = 280;
FocusItem.push(yanlis);
var yanlis2 = new Object();
yanlis2["image"] = new Image();
yanlis2.image.src = './images/odaklanma/level/'+RandomSoru+'/yanlis1.png';
yanlis2["x"] = xYanlis2;
yanlis2["y"] = 280;
FocusItem.push(yanlis2);
}
if(focusImageBackground.complete){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
else
focusImageBackground.onload=function(){
if(FocusItem[0].image.complete && FocusItem[1].image.complete && FocusItem[2].image.complete && FocusItem[3].image.complete)
drawFocus();
else
setTimeout(drawFocus,600);
}
function drawFocus(){
ftx.drawImage(focusImageBackground,0,0);
for (var i=0; i<FocusItem.length; i++){
FocusItem[i].image.onload=function(){
ftx.drawImage (FocusItem[i].image, FocusItem[i].x, FocusItem[i].y);
}
}
}
I'd suggest loading all your images, then when they are all done, you can call the rest of your code. I don't quite follow what you're trying to do with all the rest of your code, but here's a simple way to load an array of image URLs and know when they are done.
This is the general idea (I've left out lots of your code that has nothing to do with the central issue of knowing when all the images are loaded) and I've also tried to DRY up your code:
function createImagesNotify(srcs, fn) {
var imgs = [], img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
imgs.push(img);
img.onload = function() {
--remaining;
if (remaining == 0) {
fn(srcs);
}
};
// must set .src after setting onload handler
img.src = srcs[i];
}
return(imgs);
}
// here's your starting array of filenames
var fnames = ["soru.png", "dogru.png", "yanlis.png", "yanlis1.png"];
// insert your process to create RandomSoru here
var randomSoru = ....;
// build full urls array
var urls = [];
for (var i = 0; i < fnames; i++) {
urls.push('./images/odaklanma/level/' + RandomSoru + '/' + fnames[i]);
}
// load all images and call callback function when they are all done loading
var imgs = createImagesNotify(urls, function() {
// all images have been loaded here
// do whatever you want with all the loaded images now (like draw them)
});
This code is based on an earlier answer of mine here: Cross-browser solution for a callback when loading multiple images?