Alright let's see if I can explain this properly.
I am writing my own jQuery photo gallery. It loads the contents of the gallery using AJAX, calling upon a Web Method which returns a string which is an array filled with JSON objects containing data (i.e. the file name and the file path of the image and the file path for the image's thumbnail) on every file in the folder passed to it.
Like 'a so:
$(".Title").click(function (e) {
Populate($(this).text());
function Populate(folder) {
$.ajax({
type: "POST",
url: "Filenames.asmx/GetFiles",
contentType: "application/json; charset=utf-8",
data: '{ "folderName" : "'+folder+'"}',
dataType: "json",
success: OnSuccess,
failure: function (response) {
alert(response.d);
}
});
}
...//more code follows
Anyway, so, we have our OnSuccess() function:
function OnSuccess(response) {
var $thumbs = $('#Gallery_Top .viewPane .thumbPanel');
images = $.parseJSON(response.d);
$thumbs.children().each(function () {
//$(this).animate({ 'width': '0px', 'opacity': '0' }, 500).remove();
$(this).transition({ opacity: 0 }).remove();
});
//make sure the thumb reel resets to its original position
$thumbs.css('left', '0px');
for (var i = 0; i < images.length; i++) {
InsertHTML(images[i].thumbHref);
}
}
So far so good.
In the InsertHTML() function, I have to do a few things...
function InsertHTML(data) {
//create the thumbnail image
var $thumb = $('<img src="' + data + '" alt=""/>');
//set its default class to inactive
$thumb.addClass('inactive');
//bind a function to the thumbnail's click event
$thumb.bind("click", function () {
//make sure we have the current image assigned
//for navigation purposes.
$currentImage = $(this);
//remove the main image from the viewing pane
$('#Gallery_Top .viewPane .mainImage .showImage').children().animate({'opacity':'0'},500,'easeOutSine').remove();
//set all of the thumbnails to inactive
$(this).parent().children().each(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
$(this).addClass('inactive');
}
});
//set the clicked thumbnail active
$(this).addClass('active');
//get the URL for the related image
var href = data.replace('Thumbs\\', '');
href = href.replace('_thumb', '');
var $image = $('<img src="' + href + '" alt=""/>');
$image.addClass('mainImg');
$('#Gallery_Top .viewPane .mainImage .showImage')
.append($image)
.animate({ 'opacity': '1' }, 500, 'easeInSine');
});
$('#Gallery_Top .viewPane .thumbPanel').append($thumb);
}
Okay, so anyway, what's not working is every transition after the first time I click a thumbnail image. The first time I click a thumbnail, the photo fades in nicely. Ever after that, there's no transition at all.
Been yanking my hair out for about 3 hours trying to figure out a way around.
By the way, here's some CSS.
.mainImg{
display: block;
width: 75%;
height: 75%;
margin: 0 auto;
margin-top: 150px;
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
EUREKA SUCCESS I DID IT.
It never fails. I beat my head against a wall for three or four hours, trying so hard not to have to come on here and ask, then half an hour after I finally break down and ask a question, I figure it out. It's probably motivation from the shame of not knowing how to do something.
var $image = $('<img src="' + href + '" alt=""/>');
$image.on('load', function () {
$(this).animate({ 'opacity': '1' }, 500, 'easeOutSine');
});
$image.addClass('mainImg');
$image.css('opacity', '0');
$('#Gallery_Top .viewPane .mainImage .showImage').append($image);
Related
I'm currently working on a private dashboard. This dashboard should have changing background images that changes every minute (should be no problem to switch it to an hour or 20 seconds if I got it working then).
In order to do so, I registered for the [Pixabay API][1] and created the following API request
https://pixabay.com/api/?key=[my_key]f&q=nature&image_type=photo&orientation=horizontal&min_width=1920&min_height=1080&page=1&per_page=100
With that request, I get an array of 100 elements, each one containing the following information:
comments: 639
downloads: 785498
favorites: 3020
id: 736885
imageHeight: 1195
imageSize: 186303
imageWidth: 1920
largeImageURL: "https://pixabay.com/get/51e3d34b4257b108f5d0846096293076123ddee2504c704c7c2879d79048c05a_1280.jpg"
likes: 3966
pageURL: "https://pixabay.com/photos/tree-sunset-amazing-beautiful-736885/"
previewHeight: 93
previewURL: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_150.jpg"
previewWidth: 150
tags: "tree, sunset, amazing"
type: "photo"
user: "Bessi"
userImageURL: "https://cdn.pixabay.com/user/2019/04/11/22-45-05-994_250x250.jpg"
user_id: 909086
views: 2042402
webformatHeight: 398
webformatURL: "https://pixabay.com/get/51e3d34b4257b10ff3d8992cc62f3f79173fd9e64e507440722d78d39248c7_640.jpg"
webformatWidth: 640
From these 100 elements, I then randomly select one, take the largeImageURL and set it as background, together with a semi-transparent dark overlay to be able to read the text on top of it better. All this is done within a setInterval, so it happens every x milliseconds.
This is the code for it:
setInterval(function(){
$.post('getBackgroundImages.php', { }, function(data) {
var imageCollection = JSON.parse(data);
var imageNumber = Math.floor(Math.random() * 100);
var imageLink = imageCollection.hits[imageNumber].largeImageURL;
$('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+imageLink+"')");
});
},60000);
`getBackgroundImages.php' does nothing more then printing the content of the API-request.
The question now is the following: In the implemented solution, everything works, the new photo is displayed as background and switching works. However, the background is always set to a grey background for about half a second, before the image is displayed, which looks really not good, especially when often switching images.
What I'd like to get is a switching of the background without this grey background for a short time, propably even with a transition, so the change is not so abrupt...
I found a solution to first display a blured preview of the image before display the full resolution one. However, I think that this shouldn't be needed, as basically, the image has enough time to load and the background should change AFTER the image has loaded.. I do not care, if the change happens every 62 seconds, even though I set it to 60 seconds, because the image needs to load first.
Can anybody give me a hint on how to get this working better?
Thanks in advance!
[1]: https://pixabay.com/api/docs/
Maybe the most simple would be to alternate between two containers that works like backgrounds :
HTML :
<body>
<div class='bg' id='firstBg'></div>
<div class='bg' id='secondBg'></div>
<...Your Stuff...>
</body>
CSS :
body {
background: transparent;
}
.bg {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background-position: center;
z-index: -1;
background-size: cover;
transition: 3s ease-in;
}
#secondBg {
display: none;
}
JS :
setInterval(function(){
$.post('getBackgroundImages.php', { }, function(data) {
var imageCollection = JSON.parse(data);
var imageNumber = Math.floor(Math.random() * 100);
var imageLink = imageCollection.hits[imageNumber].largeImageURL;
if ($('#firstBg').css('display') == 'none') {
$('#firstBg').css("background-image","url('"+imageLink+"')");
$('#firstBg').fadeIn();
$('#secondBg').fadeOut();
}
else {
$('#secondBg').css("background-image","url('"+imageLink+"')");
$('#secondBg').fadeIn();
$('#firstBg').fadeOut();
}
});
},60000);
I did the following solution now, thanks to the hint of #zero298.
<script>
function loadImages (images) {
// each image will be loaded by this function.
// it returns a Promise that will resolve once
// the image has finished loading
let loader = function (src) {
return new Promise(function (resolve, reject) {
let img = new Image();
img.onload = function () {
// resolve the promise with our url so it is
// returned in the result of Promise.all
resolve(src);
};
img.onerror = function (err) {
reject(err);
};
img.src = src;
});
};
// create an image loader for each url
let loaders = [];
images.forEach(function (image) {
loaders.push(loader(image));
});
// Promise.all will return a promise that will resolve once all of of our
// image loader promises resolve
return Promise.all(loaders);
}
function cycleImages (images) {
let index = 0;
setInterval(function() {
// since we need an array of the image names to preload them anyway,
// just load them via JS instead of class switching so you can cut them
// out of the CSS and save some space by not being redundant
$('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+images[index]+"')");
// increment, roll over to 0 if at length after increment
index = (index + 1) % images.length;
}, 28800000);
}
$(function(){
$.post('getBackgroundImages.php', { }, function(data) {
var imageCollection = JSON.parse(data);
var imageNumber = Math.floor(Math.random() * 100);
var imageLink = imageCollection.hits[imageNumber].largeImageURL;
$('body').css("background","linear-gradient(rgba(0,0,0,.3), rgba(0,0,0,.3)),url('"+imageLink+"')");
});
$.ajax('getBackgroundImages.php',{
success:function(data) {
var parsed = JSON.parse(data);
var images = parsed.hits;
var imageUrls = [];
images.forEach(function(item,index){
imageUrls.push(item.largeImageURL);
})
loadImages(imageUrls).then(cycleImages).catch(function (err) {
console.error(err);
});
}
});
});
</script>
This first puts all imageUrls into an array, then loads all images with Promise to then display then without a big delay.. I didn't really manage to get a nice transition between switching the images, as jQuerys fade-to method lets the content of the page fade out as well, rather then only the background image...
Adding more div's / changing the structure of the page is not too easy by the way, as there is a lot of floating and other css rules to make the elements appear on various positions on the page. Adding a div around all content in order to try to give that div the background-image destroyed the hole layout...
All in all, I'm confident with this solution, however, if anybody has a good idea to make the switch more smooth, feel free to tell me :)
This is my code, to see it in action, take a look at this Fiddle
HTML
<div id="header">
.
.
.
</div>
CSS
#header {
background: url(images/img8681.jpg);
background-size: cover;
border-bottom: 8px solid #333333;
height: 620px;
}
Javasript (jQuery)
var imgs = new Array("images/img8681.jpg","","","","");
function changeBg() {
var imgUrl = imgs[Math.floor(Math.random()*imgs.length)];
$('#header').css('background-image', 'url(' + imgUrl + ')');
}
setInterval(changeBg,5000);
My question how can I have the change of the images smoothly instead of "just replace" ?
And how to avoid continuously appear of the same image ?
You can get a smoother change of the image if you use the fadeIn and fadeOut functions.
var imgs = new Array("img1.jpg","img2.jpg","img3.jpg","img4.jpg","img5.jpg");
function changeBg() {
var imgUrl = imgs[Math.floor(Math.random()*imgs.length)];
$('#header').css('background-image', 'url(' + imgUrl + ')');
$('#header').fadeIn(1000); //this is new, will fade in smoothly
}
function changeBackgroundSmoothly() {
$('#header').fadeOut(1000, changeBg); //this is new, will fade out smoothly
}
setInterval(changeBackgroundSmoothly,5000);
See this Fiddle to see the result.
Concerning the randomness of the images you can't do a lot if it does have to be random. Simply because random implies that the same image might appear twice in a row, otherwise it wouldn't be totally random as you could exclude one result.
A solution might be to not display the images randomly, but rather in a predefined sequence, refer to this site for an example.
Just another approach
$("#header").fadeOut(500, //Speed
function () { //On fadeOut complete
$(this).css("background-image", "url(img2.jpg)") //Change BG
.fadeIn(); //FadeIn
});
You can check here: https://jsfiddle.net/rafaelaca/wwjro184/
I have conversation screen to be developed i have planned to change the background images for every millisecond so that it looks like a animation. I tried using jquery settimeout and setinterval but both the ways stack of images changing in small interval hangs the browser, any ideas of how to accomplish my task.
function change_background(new_image_source) {
var myimage = $( '#spriteanim' );
myimage.attr('src','style/images/Sprites/Screen1/'+new_image_source+'.png');
console.log(myimage.attr('src'));
timer = setTimeout( function () {
new_image_source = new_image_source+1;
change_background(new_image_source);
}, 50);
if(new_image_source>=10899){
change_background(new_image_source);
clearTimeout(timer);
}
}
Changing the src attribute will never work as you want. That's because the browser needs time to load the image. Even it is cached it is still too slow for animating. I'll suggest to combine your images into sprite and change the background-position. You can even do that with pure css transition.
For example -> http://jsfiddle.net/krasimir/uzZqg/
HTML
<div class="image"></div>
CSS
.image {
background: url('...');
width: 200px;
height: 200px;
transition: all 4000ms;
-webkit-transition: all 4000ms;
}
.image:hover {
background-position: -500px 0;
}
You can even use keyframes.
Here is how you can preload your images http://jsfiddle.net/krasimir/DfWJm/1/
HTML
<div id="preloader"></div>
JS
var images = [
'http://www.australia.com/contentimages/about-landscapes-nature.jpg',
'http://www.australia.com/contentimages/about-landscapes-nature.jpg',
'http://www.australia.com/contentimages/about-landscapes-nature.jpg',
'http://www.australia.com/contentimages/about-landscapes-nature.jpg',
'http://www.australia.com/contentimages/about-landscapes-nature.jpg',
'http://www.australia.com/contentimages/about-landscapes-nature.jpg'
];
var preloader = document.getElementById("preloader");
var preloadImages = function(callback) {
if(images.length == 0) {
callback();
return;
}
var image = images.shift();
var img = document.createElement("IMG");
img.setAttribute("src", image);
preloader.appendChild(img);
img.addEventListener("load", function() {
console.log("image loaded");
preloadImages(callback);
});
}
preloadImages(function() {
// your animation starts here
alert("Images loaded");
});
Of course you may hide the #preloader div with display: none;
Checkout http://spritely.net/
It'll handle the details of animating a spritesheet. Let's you set FPS and control playback.
I think 'every millisecond' is a bit too fast.
Image load takes some time. I think, you should load all the images once, before starting the animation. It will take some time, since number of images you are using seems to be 10899. And just hide all but one every few milliseconds. 'Few milliseconds', instead of 'every millisecond', should do your job.
UPDATE:
Name your images spriteanim0, spriteanim1... like this. After all the images have been loaded, and all have been assigned display: none, call this js function:
var new_image_source1;
function change_background(prev_image_source, new_image_source) {
document.getElementById('spriteanim' + prev_image_source).style.display = 'none';
document.getElementById('spriteanim' + new_image_source).style.display = 'block';
if (new_image_source >= 10899)
new_image_source1 = 0;
else
new_image_source1 = new_image_source + 1;
window.setTimeout(
function () {
change_background(new_image_source, new_image_source1);
},
50);
}
You can try this and change the setTimeout interval value accordingly, as needed.
So i am trying to read the height and width of img elements created via jquery.
This is the code i am trying to execute
$(document).ready(function()
{
$.ajax({
url: 'res/script/getImage.php',
type: 'POST',
data: {
param : 'Load'
},
success: function(result)
{
ImageArray = JSON.parse(result);
for(i=0; i<ImageArray.length; i++)
{
//Read the Image element and update to gallery
document.getElementById("gallery").innerHTML += ImageElement;
ImageArrayComplete[ImageCounter] = ImageArray[i].image;
UserArrayComplete[ImageCounter] = ImageArray[i].user;
}
//Create Canvas
$('#gallery img').each(function() {
console.log(this);
console.log('Width=' + this.width+ 'Height='+this.height);
createCanvas(this);
});
}
});
});
The output of console.log(this); is the path for image which is as expected.
But the output of console.log('Width=' + this.width+ 'Height='+this.height); is 0 for both width and height during initial page load.
The value then resets to actual width of 200 once page is refreshed.
There is no other error thrown and happens in both firefox and chrome. What am i missing here?
Are you sure the img select has the height and width values?
your ImageElement object is undefined. try this:
change
document.getElementById("gallery").innerHTML += ImageElement;
to
$('<img/>').attr('src', ImageArray[i].image).appendTo($('#gallery'));
and this object doesn't have a height and width attribute. if you wanna get height of it, use :
console.log('Width=' + $(this).width() + 'Height=' + $(this).height());
As many of you know it is widely used to lazy load images.
Now i want to use this as lazy load div background images.
How can i do that ?
I am currently able to use http://www.appelsiini.net/projects/lazyload that plugin
So i need to modify it in a way that it will work with div backgrounds
Need help. Thank you.
The below part i suppose lazy loads images
$self.one("appear", function() {
if (!this.loaded) {
if (settings.appear) {
var elements_left = elements.length;
settings.appear.call(self, elements_left, settings);
}
$("<img />")
.bind("load", function() {
$self
.hide()
.attr("src", $self.data(settings.data_attribute))
[settings.effect](settings.effect_speed);
self.loaded = true;
/* Remove image from array so it is not looped next time. */
var temp = $.grep(elements, function(element) {
return !element.loaded;
});
elements = $(temp);
if (settings.load) {
var elements_left = elements.length;
settings.load.call(self, elements_left, settings);
}
})
.attr("src", $self.data(settings.data_attribute));
}
});
Jquery plugin lazy load
First you need to think off when you want to swap. For example you could switch everytime when its a div tag thats loaded. In my example i just used a extra data field "background" and whenever its set the image is applied as a background image.
Then you just have to load the Data with the created image tag. And not overwrite the img tag instead apply a css background image.
Here is a example of the code change:
if (settings.appear) {
var elements_left = elements.length;
settings.appear.call(self, elements_left, settings);
}
var loadImgUri;
if($self.data("background"))
loadImgUri = $self.data("background");
else
loadImgUri = $self.data(settings.data_attribute);
$("<img />")
.bind("load", function() {
$self
.hide();
if($self.data("background")){
$self.css('backgroundImage', 'url('+$self.data("background")+')');
}else
$self.attr("src", $self.data(settings.data_attribute))
$self[settings.effect](settings.effect_speed);
self.loaded = true;
/* Remove image from array so it is not looped next time. */
var temp = $.grep(elements, function(element) {
return !element.loaded;
});
elements = $(temp);
if (settings.load) {
var elements_left = elements.length;
settings.load.call(self, elements_left, settings);
}
})
.attr("src", loadImgUri );
}
the loading stays the same
$("#divToLoad").lazyload();
and in this example you need to modify the html code like this:
<div data-background="http://apod.nasa.gov/apod/image/9712/orionfull_jcc_big.jpg" id="divToLoad" />
but it would also work if you change the switch to div tags and then you you could work with the "data-original" attribute.
Here's an fiddle example: http://jsfiddle.net/dtm3k/1/
EDIT: the post from below is from 2012 and absolete by now!
I do it like this:
<div class="lazyload" style="width: 1000px; height: 600px" data-src="%s">
<img class="spinner" src="spinner.gif"/>
</div>
and load with
$(window).load(function(){
$('.lazyload').each(function() {
var lazy = $(this);
var src = lazy.attr('data-src');
$('<img>').attr('src', src).load(function(){
lazy.find('img.spinner').remove();
lazy.css('background-image', 'url("'+src+'")');
});
});
});
Mid last year 2020 web.dev posted an article that shared some new ways to do this with the the new IntersectionObserver which at the time of writing this answer is supported in all major browsers. This will allow you to use a very light weight background image, or background color placeholder while you wait for the image to come to the edge of the viewport and then it is loaded.
CSS
.lazy-background {
background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
background-image: url("hero.jpg"); /* The final image */
}
Javascript
document.addEventListener("DOMContentLoaded", function() {
var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));
if ("IntersectionObserver" in window) {
let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
lazyBackgroundObserver.unobserve(entry.target);
}
});
});
lazyBackgrounds.forEach(function(lazyBackground) {
lazyBackgroundObserver.observe(lazyBackground);
});
}
});
I've found this on the plugin's official site:
<div class="lazy" data-original="img/bmw_m1_hood.jpg" style="background-image: url('img/grey.gif'); width: 765px; height: 574px;"></div>
$("div.lazy").lazyload({
effect : "fadeIn"
});
Source: http://www.appelsiini.net/projects/lazyload/enabled_background.html
I've created a "lazy load" plugin which might help. Here is the a possible way to get the job done with it in your case:
$('img').lazyloadanything({
'onLoad': function(e, LLobj) {
var $img = LLobj.$element;
var src = $img.attr('data-src');
$img.css('background-image', 'url("'+src+'")');
}
});
It is simple like maosmurf's example but still gives you the "lazy load" functionality of event firing when the element comes into view.
https://github.com/shrimpwagon/jquery-lazyloadanything
It's been a moment that this question is asked, but this doesn't mean that we can't share other answers in 2020. Here is an awesome plugin with jquery:jQuery Lazy
The basic usage of Lazy:
HTML
<!-- load background images of other element types -->
<div class="lazy" data-src="path/to/image.jpg"></div>
enter code here
JS
$('.lazy').Lazy({
// your configuration goes here
scrollDirection: 'vertical',
effect: 'fadeIn',
visibleOnly: true,
onError: function(element) {
console.log('error loading ' + element.data('src'));
}
});
and your background images are lazy loading. That's all!
To see real examples and more details check this link lazy-doc.
Without jQuery
HTML
background-image: url('default-loading-image');
data-src="image-you-want-to-load"
<div class="ajustedBackground" style="background-image: url('default-loading-image');" data-src="image-you-want-to-load"><div>
var tablinks = document.getElementsByClassName("ajustedBackground");
for (i = 0; i < tablinks.length; i++) {
var lazy = tablinks[i];
var src = lazy.dataset.src;
lazy.style.backgroundImage = 'url("'+src+'")';
}
.ajustedBackground{
width: 100%;
height: 300px;
background-size: 100%;
border-radius: 5px;
background-size: cover;
background-position: center;
position: relative;
}
<div class="ajustedBackground" style="background-image: url('https://monyo.az/resources/img/ezgif-6-b10ea37ef846.gif');" data-src="https://monyo.az/resources-qrcode/img/Fathir_7%201.png"><div>
Finds all ajustedBackground classname in html and load image from data-src
function lazyloadImages(){
var tablinks = document.getElementsByClassName("ajustedBackground");
for (i = 0; i < tablinks.length; i++) {
var lazy = tablinks[i];
var src = lazy.dataset.src;
lazy.style.background = 'url("'+src+'")';
}
}
Lazy loading images using above mentioned plugins uses conventional way of attaching listener to scroll events or by making use of setInterval and is highly non-performant as each call to getBoundingClientRect() forces the browser to re-layout the entire page and will introduce considerable jank to your website.
Use Lozad.js (just 569 bytes with no dependencies), which uses InteractionObserver to lazy load images performantly.
I had to deal with this for my responsive website. I have many different backgrounds for the same elements to deal with different screen widths. My solution is very simple, keep all your images scoped to a css selector, like "zoinked".
The logic:
If user scrolls, then load in styles with background images associated with them.
Done!
Here's what I wrote in a library I call "zoinked" I dunno why. It just happened ok?
(function(window, document, undefined) { var Z = function() {
this.hasScrolled = false;
if (window.addEventListener) {
window.addEventListener("scroll", this, false);
} else {
this.load();
} };
Z.prototype.handleEvent = function(e) {
if ($(window).scrollTop() > 2) {
this.hasScrolled = true;
window.removeEventListener("scroll", this);
this.load();
} };
Z.prototype.load = function() {
$(document.body).addClass("zoinked"); };
window.Zoink = Z;
})(window, document);
For the CSS I'll have all my styles like this:
.zoinked #graphic {background-image: url(large.jpg);}
#media(max-width: 480px) {.zoinked #graphic {background-image: url(small.jpg);}}
My technique with this is to load all the images after the top ones as soon as the user starts to scroll. If you wanted more control you could make the "zoinking" more intelligent.
Using jQuery I could load image with the check on it's existence. Added src to a plane base64 hash string with original image height width and then replaced it with the required url.
$('[data-src]').each(function() {
var $image_place_holder_element = $(this);
var image_url = $(this).data('src');
$("<div class='hidden-class' />").load(image_url, function(response, status, xhr) {
if (!(status == "error")) {
$image_place_holder_element.removeClass('image-placeholder');
$image_place_holder_element.attr('src', image_url);
}
}).remove();
});
Of course I used and modified few stack answers. Hope it helps someone.
This is an AngularJS Directive that will do this. Hope it helps someone
Usage:
<div background-image="{{thumbnailUrl}}"></div>
Code:
import * as angular from "angular";
export class BackgroundImageDirective implements angular.IDirective {
restrict = 'A';
link(scope: angular.IScope, element: angular.IAugmentedJQuery, attrs: angular.IAttributes) {
var backgroundImage = attrs["backgroundImage"];
let observerOptions = {
root: null,
rootMargin: "0px",
threshold: []
};
var intersectionCallback: IntersectionObserverCallback = (entries, self) => {
entries.forEach((entry) => {
let box = entry.target as HTMLElement;
if (entry.isIntersecting && !box.style.backgroundImage) {
box.style.backgroundImage = `url(${backgroundImage})`;
self.disconnect();
}
});
}
var observer = new IntersectionObserver(intersectionCallback, observerOptions);
observer.observe(element[0]);
}
static factory(): angular.IDirectiveFactory {
return () => new BackgroundImageDirective();
}
}
<div class="lazy" data-bg="img/bmw_m1_hood.jpg" style="width: 765px; height: 574px;"></div>
var lazyLoadInstance = new LazyLoad({
load_delay: 100,
effect : "fadeIn"
});
using the vanilla lazyload
https://www.npmjs.com/package/vanilla-lazyload
I know it's not related to the image load but here what I did in one of the job interview test.
HTML
<div id="news-feed">Scroll to see News (Newest First)</div>
CSS
article {
margin-top: 500px;
opacity: 0;
border: 2px solid #864488;
padding: 5px 10px 10px 5px;
background-image: -webkit-gradient(
linear,
left top,
left bottom,
color-stop(0, #DCD3E8),
color-stop(1, #BCA3CC)
);
background-image: -o-linear-gradient(bottom, #DCD3E8 0%, #BCA3CC 100%);
background-image: -moz-linear-gradient(bottom, #DCD3E8 0%, #BCA3CC 100%);
background-image: -webkit-linear-gradient(bottom, #DCD3E8 0%, #BCA3CC 100%);
background-image: -ms-linear-gradient(bottom, #DCD3E8 0%, #BCA3CC 100%);
background-image: linear-gradient(to bottom, #DCD3E8 0%, #BCA3CC 100%);
color: gray;
font-family: arial;
}
article h4 {
font-family: "Times New Roman";
margin: 5px 1px;
}
.main-news {
border: 5px double gray;
padding: 15px;
}
JavaScript
var newsData,
SortData = '',
i = 1;
$.getJSON("http://www.stellarbiotechnologies.com/media/press-releases/json", function(data) {
newsData = data.news;
function SortByDate(x,y) {
return ((x.published == y.published) ? 0 : ((x.published < y.published) ? 1 : -1 ));
}
var sortedNewsData = newsData.sort(SortByDate);
$.each( sortedNewsData, function( key, val ) {
SortData += '<article id="article' + i + '"><h4>Published on: ' + val.published + '</h4><div class="main-news">' + val.title + '</div></article>';
i++;
});
$('#news-feed').append(SortData);
});
$(window).scroll(function() {
var $window = $(window),
wH = $window.height(),
wS = $window.scrollTop() + 1
for (var j=0; j<$('article').length;j++) {
var eT = $('#article' + j ).offset().top,
eH = $('#article' + j ).outerHeight();
if (wS > ((eT + eH) - (wH))) {
$('#article' + j ).animate({'opacity': '1'}, 500);
}
}
});
I am sorting the data by Date and then doing lazy load on window scroll function.
I hope it helps :)
Demo