Preloading images on safari for background image change [duplicate] - javascript

This question already has answers here:
Preloading images with jQuery
(20 answers)
Preload background image
(5 answers)
Closed 5 years ago.
I have a background that changes every 12seconds.
In Chrome, Firefox and Opera the background change is works fine, but in Safari the browser always loads the image again and that is noticed by a flickering on every image change on the first cycle. Any ideas on how can I solve this problem.
This is how I'm handling the background change:
var img2 = new Image();
var img3 = new Image();
img2.src="/img/bg2.png";
img3.src="/img/bg3.png";
Meteor.setInterval(function(){
let elem = $(".header-2");
if(elem.hasClass("bg1")){
elem.removeClass("bg1");
elem.addClass("bg2");
let src = 'url('+img2.src.replace(location.origin,'')+')';
elem.css("background-image", src);
}
else if(elem.hasClass("bg2")){
elem.removeClass("bg2");
elem.addClass("bg3");
let src = 'url('+img3.src.replace(location.origin,'')+')';
elem.css("background-image", src);
}
else{
elem.removeClass("bg3");
elem.addClass("bg1");
}
}, 12*1000)
The css classes:
.header-2.bg1 {
background-image: url('/img/bg1.png');
}
.header-2.bg2 {
}
.header-2.bg3 {
}

Changing the background after an onload event on the image should ensure the image is completely loaded before updating anything on the page.
This approach adds the event and keeps the background changes in JS.
var bgs = ['http://3.bp.blogspot.com/_EqZzf-l7OCg/TNmdtcyGBZI/AAAAAAAAAD8/KD5Y23c24go/s1600/homer-simpson-1280x1024.jpg', 'http://cdn.thedailybeast.com/content/dailybeast/articles/2015/03/31/neil-degrasse-tyson-defends-scientology-and-the-bush-administration-s-science-record/jcr:content/image.img.2000.jpg/1432067001553.cached.jpg','http://www.mrwallpaper.com/wallpapers/Huge-Bear.jpg'],
count = 1,
header2 = document.getElementsByClassName('header-2')[0];
setInterval(function() {
var img2 = new Image(),
url = bgs[count];
img2.onload = function() {
header2.style.backgroundImage = 'url(' + url + ')';
}
img2.src = url;
(count < (bgs.length - 1)) ? count++ : count = 0;
},1000)
body {
margin: 0;
}
.header-2 {
background-position: top center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
margin: 0;
background-image: url('http://3.bp.blogspot.com/_EqZzf-l7OCg/TNmdtcyGBZI/AAAAAAAAAD8/KD5Y23c24go/s1600/homer-simpson-1280x1024.jpg');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="header-2"></header>
You can also use the same method with your code where you're using CSS to control parts of it. Here I just set a data-bg attribute in your interval, then control the background-image (and whatever else) via CSS using the data selector
var bgs = ['http://3.bp.blogspot.com/_EqZzf-l7OCg/TNmdtcyGBZI/AAAAAAAAAD8/KD5Y23c24go/s1600/homer-simpson-1280x1024.jpg', 'http://cdn.thedailybeast.com/content/dailybeast/articles/2015/03/31/neil-degrasse-tyson-defends-scientology-and-the-bush-administration-s-science-record/jcr:content/image.img.2000.jpg/1432067001553.cached.jpg', 'http://www.mrwallpaper.com/wallpapers/Huge-Bear.jpg'],
count = 0,
header2 = document.getElementsByClassName('header-2')[0];
setInterval(function() {
var img2 = new Image(),
url = bgs[count];
img2.onload = function() {
header2.setAttribute('data-bg', count);
}
img2.src = url;
(count < (bgs.length - 1)) ? count++ : count = 0;
}, 1000)
body {
margin: 0;
}
.header-2 {
background-position: top center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
margin: 0;
background-image: url('http://3.bp.blogspot.com/_EqZzf-l7OCg/TNmdtcyGBZI/AAAAAAAAAD8/KD5Y23c24go/s1600/homer-simpson-1280x1024.jpg');
}
.header-2[data-bg="1"] {
background-image: url('http://cdn.thedailybeast.com/content/dailybeast/articles/2015/03/31/neil-degrasse-tyson-defends-scientology-and-the-bush-administration-s-science-record/jcr:content/image.img.2000.jpg/1432067001553.cached.jpg');
}
.header-2[data-bg="2"] {
background-image: url('http://www.mrwallpaper.com/wallpapers/Huge-Bear.jpg');
}
<header class="header-2" ></header>

this is possibly due to images not loading properly before the script is being executed by calling the function onload() will do the trick.

Related

JavaScript rapidly change background-img property without performance issues

I have a script which changes the background-img property of multiple divs, every 20ms.
var frames = ["57.png", "59.png", "60.png"]
var currentframe = 0;
var frame_loop = setInterval(function () {
if (currentframe == 3) {
currentframe = 0;
} else {
for (var i = 0; i < $(".my-element").length; i++) {
$(`.my-element:nth-child(${i + 1})`).css("background-image", `url(assets/loop/${frames[currentframe]})`);
}
currentframe++;
}
}, 20);
The script above works as it should, however I experience some performance issues - and i'm assuming it's because the background-img is changing quite fast.
Is there anyway I could fix this issue? I don't mind using libraries. Would I need to resort to using gifs? Is it possible to use gifs with background-img?
Thanks for any feedback.
Here is an example of how I would do it (may not be the most performant, but might help):
var frames = [
"https://a.wattpad.com/useravatar/Kitten6416.256.440418.jpg",
"https://i.pinimg.com/474x/b5/e1/be/b5e1bef76b2058910f556c85c1040b79.jpg",
"https://a.wattpad.com/useravatar/Vendedora_De_Meng.128.220869.jpg"
];
var currentFrame = 0,
loopRunning = confirm("Warning! This page might trigger epileptic seizures. Continue?"),
// Don't calculate those every time
elems = document.querySelectorAll('.my-element'),
nbElems = elems.length;
(function frame_loop() {
if (loopRunning) {
// Calculate this once before the loop
var background = `url(${frames[currentFrame]})`;
for (var i = 0; i < nbElems; i++) {
elems[i].style.backgroundImage = background;
}
currentFrame = ++currentFrame % nbElems;
requestAnimationFrame(frame_loop);
}
})();
.my-element {
display: inline-block;
width: 100px;
height: 100px;
background-size: cover;
background-position: center;
}
<div class="my-element"></div>
<div class="my-element"></div>
<div class="my-element"></div>

Preload image to change css background from a url link

I am loading images from my unsplash collection (https://unsplash.com/collections/3132360/dashboard) and changing the background image of the body (through CSS). It works, but there is a delay in the change. Is there a way I can preload the images and maybe even fade them in/out?
I have tried the new Image() of javascript, but that is for HTML images and not CSS.
Thanks in advance :)
Here is the jquery:
$('document').ready(function(){
var x = 0;
loadImage(x);
});
function loadImage(x) {
x +=1;
var image = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x;
setTimeout(function() {
imgSwap(image, x);
}, 30000)
}
function imgSwap(image, x){
$('body').css('background-image', 'url(' + image + ')');
loadImage(x);
}
You can add default image to body style in css to show the preload image.
body{
background-image: url("http://www.ajaxload.info/cache/FF/FF/FF/00/00/00/5-1.gif");
background-repeat: no-repeat;
}
https://jsfiddle.net/nimittshah/cwpdsnLy/
This updated code now works, using img.src as the background URL for the CSS refreshes the image as needed. Using just the image variable as the URL does not.
$('document').ready(function(){
var x = 0;
loadImage(x);
});
function loadImage(x) {
x +=1;
var image = new Image()
image.src = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x;
setTimeout(function() {
imgSwap(image, x);
}, 30000)
}
function imgSwap(image, x) {
$('body').css('background-image', 'url(' + image.src + ')');
loadImage(x);
}
I think if you can include this following javascript code and css, it might be able to full fill what you want to achieve
function preloader() {
if (document.getElementById) {
document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";
document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";
document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(preloader);
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
var x = 0;
$('document').ready(function(){
loadImage(x);
});
function loadImage(x) {
setInterval(function() {
var randomId = new Date().getTime();
var image = 'https://source.unsplash.com/collection/3132360/1920x1080#'+x+'?r='+randomId;
console.log("x="+x + " " + image);
imgSwap(image);
x +=1;
}, 30000)
}
function imgSwap(image){
$('body').css('background-image', 'url(' + image + ')');
//$('#bg_img').attr('src', image);
}
You can change value of x randomly, but i have found your img provider is not returning the images plz check this first, It is redirecting to some other url
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<!--<img id="bg_img" src="" width=400 height=400/>-->

change background-image of div with animation

I would like to create a little slider to change background-image of my div every seconds.
My code doesn't work for the moment, image is not changed. And ideally, i would like that the script run in infinite mode..
HTML
<div id="slidesPartenairesHome"></div>
CSS
#slidesPartenairesHome {
background-size: contain;
background-position: center center;
width: 300px;
height: 170px;
margin-left: 120px;
}
JS
$( document ).ready(function() {
var arrayOfPartenaires = [
"images/partenaires/a.png",
"images/partenaires/b.jpg",
"images/partenaires/c.jpg",
"images/partenaires/d.png",
"images/partenaires/e.png",
"images/partenaires/f.jpg",
"images/partenaires/g.jpg",
"images/partenaires/h.jpg",
"images/partenaires/i.png",
"images/partenaires/j.jpg",
"images/partenaires/k.jpg",
"images/partenaires/l.jpg"
];
for (var i=0; i<arrayOfPartenaires.length; i++) {
var currentPartenaireImg = arrayOfPartenaires[i];
$('#slidesPartenairesHome').animate({opacity: 0}, 'slow', function() {
$(this).css({'background-image': 'url("'+currentPartenaireImg+')'}).animate({opacity: 1});
});
}
});
You could use window.setinterval, you could also use setTimeout but setinterval is a litle bit more precise.
Example with setinteval:
window.setInterval(function(){
var url = getCurrent();
//start animation
$('#slidesPartenairesHome').delay( 500 ).fadeTo(500, 0.3, function()
{
$(this).css('background-image', 'url(' + url + ')');
}).fadeTo('slow', 1);
}, 1000);
// We start with index of 1 because we want to skip the first image,
// Else we would be replacing it with the same image.
var index = 1;
var arrayOfPartenaires = [
"http://yourdomain.com/images/partenaires/a.png",
"http://yourdomain.com/images/partenaires/b.png",
"http://yourdomain.com/images/partenaires/c.png"
];
function getCurrent(){
// We check if the index is higher than the ammount in the array.
// If thats true set 0 (beginning of array)
if (index > arrayOfPartenaires.length -1){
index = 0;
}
var returnValue = index;
index ++;
return arrayOfPartenaires[returnValue];
}
Note if you really want to change the image every 1 second the background will be changing very fast.
Fiddle
I hope this may help you
html
<div id="slidesPartenairesHome">
<div id="imags">
</div>
</div>
Css
#slidesPartenairesHome
{
margin-left: 120px;
}
#slidesPartenairesHome, #imags
{
background-size: contain;
background-position: center center;
width: 300px;
height: 170px;
}
Js
$(function () {
var arrayOfPartenaires = [
"http://fotos2013.cloud.noticias24.com/animales1.jpg",
"http://www.schnauzi.com/wp-content/uploads/2013/03/animales-en-primavera.jpg",
"https://johannagrandac.files.wordpress.com/2015/01/conejos.jpg",
"http://png-4.findicons.com/files/icons/1035/human_o2/128/face_smile.png",
"http://icons.iconarchive.com/icons/rokey/the-blacy/128/big-smile-icon.png",
"http://simpleicon.com/wp-content/uploads/smile-256x256.png"
];
var loaders = 0;
function cycleImages() {
var element = arrayOfPartenaires[loaders];
$("#imags").css({ 'background-image': 'url(' + element + ')' }).animate({ opacity: 1 }).hide().fadeIn("slow");
if (loaders < arrayOfPartenaires.length) {
loaders = loaders + 1;
if (loaders >= arrayOfPartenaires.length) {
loaders = 0;
}
}
else {
loaders = 0;
}
console.log(loaders, arrayOfPartenaires[loaders]);
}
cycleImages();
setInterval(function () { cycleImages() }, 3000);
});
jsFiddel Demo

JavaScript dymanically change CSS background style

I am trying to dynamically change my background image by continuously looping through an array of image paths. The code works if I log the output to a console, but I cannot get the image to actually change.
Original CSS: (I am overriding the default style from another CSS file)
<style>
.jumbotron {
background: #7da7d8 url('images/rotunda2.jpg') no-repeat center center !important;
}
</style>
JavaScript:
$(document).ready(function () {
var count = -1;
var images=new Array("images/image1.jpg","images/image2.jpg","images/image3.jpg");
setInterval(swap, 5000);
function swap(){
$('.jumbotron').css("background", "#7da7d8 url('"+images[++count % images.length]+"') no-repeat center center !important");
console.log(images[++count % images.length]);
}
});
Any ideas?
You're swap function seems kind of odd. Typically for something like this, you could have a counter that gets incremented and then just resets to 0 and starts over. Also make sure you are running in an onload event handler context.
var count = 0;
var images=new Array("images/image1.jpg","images/image2.jpg","images/image3.jpg");
function swap(){
//get the next image
var nextImage = images[count];
console.log(nextImage);
$('.jumbotron').css("background-image", nextImage);
//increment count
count = count > images.length - 1 ? 0 : count+=1;
}
$(document).ready(function(){
setInterval(swap, 5000);
});
aside from that, make sure to check your error console for errors, and for 404's indicating you might have bad image paths
Try this:
$(document).load(function() {
var count = -1;
var images = ['images/image1.jpg', 'images/image2.jpg', 'images/image3.jpg'];
setInterval(swap, 5000);
function swap() {
var img = images[++count % images.length];
$('.jumbotron').css('background', '#7da7d8 url(' + img + ') no-repeat center center !important');
console.log(img);
}
});
I don't think change css is a good idea, you may define some classes, and dynamically change the classes on the element!
html:
<div class="dynamicBg class1"></div>
<div class="dynamicBg class1"></div>
css:
.dynamicBg {
background-color: #7da7d8;
background-repeat: no-repeat;
background-position: center center;
}
.class1 {
background-image: url('images/image1.jpg');
}
.class2 {
background-image: url('images/rotunda2.jpg');
}
.class3 {
background-image: url('images/rotunda3.jpg');
}
.class4 {
background-image: url('images/rotunda4.jpg');
}
js:
$(function() {
var classStr = 'class1 class2 class3 class4',
classArr = classStr.split(' '), i = 0,
$dynamicBg = $('.dynamicBg');
setInterval(function() {
i = i > 3 ? 0 : i + 1;
$dynamicBg.removeClass(classStr).addClass(classArr[i]);
}, 5000);
});
Wait for the document to load:
$(document).load(function()
{
var count = -1;
var images=new Array("images/image1.jpg","images/image2.jpg","images/image3.jpg");
setInterval(swap, 5000);
function swap(){
$('.jumbotron').css("background", "#7da7d8 url("+images[++count % images.length]+") no-repeat center center !important");
console.log(images[++count % images.length]);
}
});

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