Loading images faster on a website in java script - javascript

I am trying to import photos from a local file on my computer to my HTML file. I have managed to do this but I need to speed up the time it takes to load in on the page, 2.4mins. My idea was to load a smaller file size of the image, 200px by 200px and then load the full-sized image in the background. The problem that I am encountering is that I am not able to integrate my code of loading the images from a local file with the lazy loading code. can anyone help?
const $spans = $("span");
const {
length
} = $spans;
$spans.each(function(i) {
$(this).append("<img src='Images/With Out Logo/Insta Photo-" + (length - i) + ".JPG' />");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<span class="Images"></span>

I'd look into using intersection observerAPI for lazy loading images, there's an excellent Google Developer Guide on this whole subject.
A basic example of this is:
Alter your <img> tags to add:
data-src
data-srcset
These point to the image to load once the element is being looked at in the "viewport".
Example:
<img class="lazy" src="placeholder.jpg" data-src="lazy-img-1x.jpg" data-srcset="lazy-img-1x.jpg 1x">
Then in a <script> tag or wherever you run your page's code just have a function that listens for the DOMContentLoaded event:
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to a more compatible method here
}
});
Here's a CodePen from the guide with a better example.

Before you upload images for use on a website, you should optimize them first to prevent slow load time/your current issue.
As your images are seemingly stored in a local folder, I would suggest to first, make a back-up of the folder containing the images [to an external hard drive or another area of your hard drive].
Then, visit an image compression site (such as tinypng, - I use this but there are others, e.g CompressJpeg) Compressing images will greatly reduce the file size but the images will appear the same. You can upload multiple images at a time, and download bundles of compressed images as a zip. Ensure that when you extract the images, that they are named as you would like (and that they don't have a '1' at the end [as usually added, to indicate that the file is a copy/2nd version])
When you run your code using the smaller images, you should find that your processing time is reduced substantially.
Hope this helps
A sidenote - Both the afore-mentioned websites handle both jpgs and png formats - the website names can be misleading! :)

Related

HTML, how to set multiple src attributes for image in parallel, fastest win

I want to asynchronously download image, so first user sees a low resolution image, and higher resolution version is downloaded in the background. I have tried the following.
<html>
<head>
<script>
window.addEventListener('load', function () {
var kuvaEl = document.getElementById('kuva');
var r_src = kuvaEl.getAttribute('r-src');
var a_src = kuvaEl.getAttribute('a-src');
kuvaEl.setAttribute('src', r_src);
kuvaEl.setAttribute('src', a_src);
});
</script>
</head>
<body>
<img id="kuva" src="http://www.viikonloppu.com/wp-content/uploads/2014/04/lotoflaughters.com_-619x428.jpg?c3bc1b"
a-src="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
r-src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
</body>
</html>
But the problem is r_src download is aborted when src is change second time. I want to download both of these images in parallel, and show the r_src first (only if it downloads faster than a_src), and when the *a_src *is ready, show the a_src.
Also, is it possible to download these a_src and r_src images to the browser cache before the src is actually changed? Ideally I would like the the src change to either retrieve the image from the cache or join the pending download for that url.
I can also use jQuery. IE7 must support the implementation.
You just need to use javascript or jquery and load two version of the same image. the first will be your low res, but you will download a high res inside an hidden img tag.
When the download is complete, you just hide / delete the low res image and show the high res.
This link show some test and few way to do it. And it should support ie7 Load a low-res background image first, then a high-res one
You can use interlaced progressive JPEG format.
This method is the preferred method for handling high quality images and has been implemented by so many websites.the idea is that the compression of the image is made in such away that the when you send the image the receiver gets the image in finer and finer detail has the sending of the data progressed.
if you dont want to use the abouve technique
Have the low quality image in the src of the image. once the whole page loaded successfully,change the low quality image with high quality image
<img id="target-image" src="low-quality.jpg" data-src="high-quality.jpg" />
$(window).load(function(){
var imgSrc = $('#target-image').data('src');
$('#target-image').attr('src',imgSrc);
});
You should put your low res as default src. Then use JS to download the high res version and on download completion, change image src.
Also, good practice is to use data-* for custom attributes
If your really want a parallel download, you should replace "load" event for the "DOMContentLoaded" event. However, this will extend the time your user has to wait until page is ready. Your should keep the load event to prioritize critical assets loading (scripts and stylesheets)
window.addEventListener('load', function() {
// get all images
let images = document.getElementsByClassName("toHighRes");
// for each images, do the background loading
for (let i = 0; i < images.length; i++) {
InitHighResLoading(images[i]);
}
});
function InitHighResLoading(image) {
let hrSrc = image.dataset["hr"];
let img = new Image();
img.onload = () => {
// callback when image is loaded
image.src = hrSrc;
}
// launch download
img.src = hrSrc;
}
img {
/* only for code snippet */
max-height: 300px;
}
<img class="toHighRes"
data-hr="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />

Fastest way to preload/load large images

Preload may not be the correct term...
I have a page which loads a very large image. I wanted to wait for the large image to completly load before displaying on the page for the user.
At the moment, I have a loading gif and i'm using javascript to wait for the image to load and then replace the loading gif src with the image:
<img src="loading.gif" id="image" />
<script>
img = 'very_large_image.jpg';
var newimg = new Image();
newimg.src = img;
newimg.onload = function(){
$('#image').attr('src',img);
}
</script>
I'm wondering if there are quicker ways to load this image such as a pure CSS way or some way to force the browser to download this asset first. The code above is obviously positioned in the location where the image is expected to load. So there is code above and below.
One CSS option I thought was to position the image off the screen and once it's loaded, perform the src replace.
My server is running http2, so it should be pretty quick. I just want to know if there is a better way then what i'm doing now to ensure the large image is loaded the quickest way possible for all major browsers.
I should add, i've already done plenty of optimisation of the image file already. I'm working with high resolution photography.
Thanks!
You can make the JPG progressive and then just let it load. Browsers will progressively display the image first blurry and then load more details.
This is the best way because user can see the image even before it's fully loaded.
Edit:
On linux use jpegtran, on Windows use Photoshop or RIOT
Your doing a great job!
Here is what I came up with:
https://jsfiddle.net/Vandeplas/jkwweh52/
HTML:
<img src="http://loadinggif.com/images/image-selection/32.gif" large-src="http://www.planwallpaper.com/static/images/518079-background-hd.jpg" large-class="fancyImg">
JS:
$('img[large-src]').each(function() {
var img = $(this);
var newimg = new Image();
newimg.src = img.attr('large-src');
newimg.setAttribute('class', img.attr('large-class'));
newimg.onload = function() {
img.replaceWith(newimg);
};
});
That separates the JS from the HTML + you can easily add infinite more pre-loading images without having to change the js!
Very easy way to preload images which are needed later
$.preloadImages = function() {
for (var i = 0; i < arguments.length; i++) {
$("<img />").attr("src", arguments[i]);
}
}
$.preloadImages("hoverimage1.jpg","hoverimage2.jpg");
I think that the best solution for your problem is split this image and load the parts assync at the same time

HTML - Display animation while JavaScript loads

I'm using this JavaScript to preload few images on my website.
var images = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
}
preload(
"img/1.png",
"img/hover.png",
"img/image.png",
"img/work1.png"
)
This code is linked in HEAD of the site.
But when someone is visiting my website he waits for few second's while images are loaded and in that time he sees blank (white) website until JS files are loaded. I want to make that when someone visit my website he see a "Loading progess bar" or message that say "Wati until page is loaded" etc. Without a blank index page where JavaScript is linked
Unless an accurate progress bar is actually helpful to your users you are probably better off simply use an animated gif that gets hidden after your loading functions finish. Something like this:
Put the gif on the top of your index.html file. Something like
<div id="loading-gif"><img src="/path/to/gif"></div>
Then when your content loads, simply execute something like
document.getElementById("loading-gif").style.display = 'none';
Note, license information for the above image is located here.

On a Web page - How to show a (light) image and replace it with a (heavy) one when the latter is downloaded by client?

I'm a beginner front-ender considering the following scenario :
A certain HTML page should include a heavy image (e.g - animated gif) but I don't want to force the client to sluggishly wait for it to completely download before enjoying a pretty page, rather I would prefer to show him a lightweight image (e.g - the first frame of the gif) and when the former is readily downloaded by the client's browser, replace the light one with the heavy.
What should be the best approach for the matter - Am I looking for a technological solution or a methodological one?
Thanks!
You can embed the light-weight image using a data-URL. This will show that image immediately.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
You can use this web site to convert an image file to a data-URL.
What you then need to do is to load the larger image in the background and, once loaded, make it replace the light-weight image.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
<img class="heavy" src="http://server.com/path/to/heavy/weight/image.gif" />
The following CSS hides the heavy-weight image initially:
/* Don't show heavy-weight images until they're loaded */
img.heavy {
display: none;
}
The following jQuery-based javascript will hide the light-weight image and show the heavy-weight image once it is loaded:
$(function () {
// Register handler that will be invoked when a heavy-weight image is loaded
$("img.heavy").on("load", function () {
// Hide the light-weight image
// (we assume that it is the immediate previous 'img' sibling of the
// heavy-weight image)
$(this).prev("img").hide();
// Show the heavy-weight image
$(this).show();
});
});
Update (not using data-URL)
If you don't want to use data-URL for the light-weight image, you can use a similar approach where you don't start loading the heavy-weight image until the light-weight is loaded.
<img class="light" src="http://server.com/path/to/light.gif" />
<img class="heavy" data-src="http://server.com/path/to/heavy.gif" />
The heavy-weight image is not loaded initially because it does not have a src-attribute.
The following script will start loading heavy-weight images (by copying data-src to src) as soon as the light-weight image is loaded, and finally "replace" the light-weight image once the heavy-weight image is loaded.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Start loading heavy image (by assigning the src-attribute)
$(this).next("img.heavy").each(function () {
$(this).attr("src", $(this).attr("data-src"));
}).on("load", function () {
// Show the heavy-weight image and hide the light-weight image
$(this).show().prev("img.light").hide();
});
});
});
Update 2 (automatic creation of heavy-weight image element)
If you can derive heavy-weight URLs from light-weight URLs, then you can use another approach which might be easier to use and maintain.
<img class="light" src="img/light/image.gif" />
The following script will create a new heavy-weight image element for each light-weight image that is loaded. The heavy-weight image URL is copied from the light-weight image URL, but with the text light replaced by heavy.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Create heavy-weight image element after the light-weight image
// URL is computed from light weight image (by replacing 'light' with 'heavy')
// The element is initially hidden.
$("<img/>")
.attr("src", $(this).attr("src").replace("light", "heavy"))
.hide()
.on("load", function () {
// Show the heavy-weight image and remove the light-weight image
$(this).show().prev("img.light").remove();
})
.insertAfter(this);
});
});
This version also removes the light-weight image from the DOM once the heavy-weight image is loaded.
I may use another simple solution depend on a hidden iframe for the heavy image. It will replace the src of the light image when the iframe is loaded. The iframe src will be the src of the heavy image.
<html>
<head>
<script>
function replaceImg(imgId,ifrId){
ifr = document.getElementById(ifrId);
img = document.getElementById(imgId);
img.src = ifr.src;
}
</script>
</head>
<body>
<img id="img1" src="../img/initializing.png" />
<iframe id="ifr1" onload="replaceImg('img1','ifr1')" src="http://lorempixel.com/800/400" style="display:none"></iframe>
</body>
</html>
A live DEMO is found here. However, if you could not able to notice the light image, press RUN button again in the jsfiddle page.

Change loading order of images already on page

Is there any way without AJAX of changing the loading order of images on a page? Or even a way to completely halt or pause loading of images already present?
The use case is simple - I have a long list of images down a page, and visitors will be landing on different spots of the page using URL anchors (/images#middle-of-page) that refer to actual containers for those images.
I'd like in the least to load the images inside the requested container FIRST, then continue loading the rest of the images.
The challenge is that there is no way to know the image paths of the requested container image before loading the page DOM.
I've tried getting the container img contents on load, then using the Javascript new Image() technique, but it doesn't change the fact that that image on the page will still be waiting for all previous images to load.
I've also tried immediately prepending a div in the body with a background image (CSS) of said img path, but this also does not prioritize the image load.
Any other ideas?
You need to have a DOM with empty img placeholders, i.e.
<img src="" mysrc="[real image url here]" />
Or you can make images to display "Loading..." image by default. You can even cache real image url in some custom tag, mysrc for example. Then once you know what exactly images you want to show (and in what order) you need to build a sequence of image loading
var images = [];//array of images to show from start and in proper order
function step(i){
var img = images[i++];
img.onload = function(){
step(i);
}
img.src = "[some url here]"
}
Hope this helps.
For interest, this is the function I ended up implementing based on the answers here (I made it an on-demand loading function for optimum speed):
function loadImage(img) { // NEED ALTERNATE METHOD FOR USERS w/o JAVASCRIPT! Otherwise, they won't see any images.
//var img = new Image(); // Use only if constructing new <img> element
var src = img.attr('alt'); // Find stored img path in 'alt' element
if(src != 'loaded') {
img
.load(function() {
$(this).css('visibility','visible').hide().fadeIn(200); // Hide image until loaded, then fade in
$(this).parents('div:first').css('background','none'); // Remove background ajax spinner
$(this).attr('alt', 'loaded'); // Skip this function next time
// alert('Done loading!');
})
.error(function() {
alert("Couldn't load image! Please contact an administrator.");
$(this).parents('div:first').find("a").prepend("<p>We couldn't find the image, but you can try clicking here to view the image(s).</p>");
$(this).parents('div:first').css('background','none');
})
.attr('src', src);
}
}
The img loading="lazy" attribute now provides a great way to implement this.
With it, images load automatically only when on the viewport. But you can also force them to load by setting in the JavaScript:
document.getElementById('myimg').loading = 'eager';
I have provided a full runnable example at: How do you make images load lazily only when they are in the viewport?
One really cool thing about this method is that it is fully SEO friendly, since the src= attribute contains the image source as usual, see also: Lazy image loading with semantic markup

Categories