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.
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 :)
I trying to make what appears to the user to be an image fader. A string of images fade into each other. All the solutions that I found were complex, and normally required an for every image. I've come up with what should be a simple solution. It's working 90% on Firefox/Chrome/IE11 on Windows. On Android Chrome it's having issues.
Basically my idea is, I have two divs, absolutely positioned, one on top of the other. Both start with a background, sized to cover. The top one fades out, revealing the bottom one, and at the end of the animation, the background-image of the top one (current hidden) is changed to image 3. After a pause, it fades back in, and the background-image of the bottom one is changed to image 4. This repeats indefinitely.
HTML:
<div class="slideshow" id="slideshow-top"></div>
<div class="slideshow" id="slideshow-bottom"></div>
CSS:
.slideshow {
display:block;
background-size:cover;
width: 100%;
height: 100%;
position:absolute;
top:0;
left:0;
}
#slideshow-top {
z-index:-5;
background-image:url(http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg);
}
#slideshow-bottom {
z-index:-10;
background-image:url(http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg);
}
Javascript:
var url_array = [
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-3.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-4.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-5.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-6.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-7.jpg',
'http://www.walldoze.com/images/full/2013/12/04/wallpapers-desktop-winter-nature-x-wallpaper-backgrounds-natureabstract-designs-interesting-hd-19045.jpg'
];
var count = 1;
setInterval(function() {
if (count%2) { // Fade In
jQuery('#slideshow-top').animate({opacity:0}, '200000', function() {
jQuery('#slideshow-top').css('background-image','url('+url_array[count]+')');
});
}
else { //Fade Out
jQuery('#slideshow-top').animate({opacity:1}, '200', function() {
jQuery('#slideshow-bottom').css('background-image','url('+url_array[count]+')');
});
}
count = (count == url_array.length-1 ? 0 : count + 1);
}, 2000);
http://jsfiddle.net/5eXy9/
As seen in the Fiddle above, this mostly works. However, it seems to ignore the length of the animation. Using .fadeOut has the same effect. I've tried going from 200 to 20000, and there doesn't seem to be a difference.
I'm not sure if this is tied into the other issue, which is that on Android (Galaxy S4, Chrome, Android 4.x), the animation doesn't occur at all. It simply changes images. Any ideas?
EDIT: Jan 10 - Timing problem is fixed, but the main issue (Android) is still unsolved. Any thoughts?
The interval keeps going, so when increasing the animation speed, you have increase the interval speed as well.
The way you've built this, you should always keep the speed of both animations equal to the interval, or if you need a delay, increase the interval compared to the animations so it at least has a higher number than the highest number used in the animations.
The reason changing the speed doesn't work at all for you, is because it should be integers, not strings, so you have to do
jQuery('#slideshow-top').animate({opacity:0}, 200000, function() {...
// ^^ no quotes
I would do something like this
var url_array = [
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-3.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-4.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-5.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-6.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-7.jpg',
'http://www.walldoze.com/images/full/2013/12/04/wallpapers-desktop-winter-nature-x-wallpaper-backgrounds-natureabstract-designs-interesting-hd-19045.jpg'];
var count = 1;
var speed = 2000,
delay = 1000;
$.each(url_array, function(source) { // preload
var img = new Image();
img.src = source;
});
setInterval(function () {
if (count % 2) { // Fade In
jQuery('#slideshow-top').animate({
opacity: 0
}, speed, function () {
jQuery('#slideshow-top').css('background-image', 'url(' + url_array[count] + ')');
});
} else { //Fade Out
jQuery('#slideshow-top').animate({
opacity: 1
}, speed, function () {
jQuery('#slideshow-bottom').css('background-image', 'url(' + url_array[count] + ')');
});
}
count = (count == url_array.length - 1 ? 0 : count + 1);
}, speed + delay);
FIDDLE
I'm looking for a way to emulate the CSS #keyframes animations using jQuery.
I need to change the background image each x seconds following a list of images provided when the user moves mouse over an element.
The CSS animations should be:
.readon:hover {
animation: readonin 2s;
}
#keyframes readonin {
0% { background-image: url(1.png); }
50% { background-image: url(2.png); }
100% { background-image: url(3.png); }
}
I've found plugins like Spritely but they works with sprites and I need instead to change the image background of the element.
Use the set-interval function of Javascript seems a bad solution because I can't find a way to stop the animation when the user moves the mouse out of the element.
Use something like...
var images = ["1.png", "2.png", "3.png"];
var $element = $(".readon");
var interval = null;
$element.hover(function () {
var $this = $(this);
var i = 0;
var fn = function () {
$this.css("background-image", "url(" + images[i] + ")");
i = ++i % images.length;
};
interval = setInterval(fn, 666);
fn();
},
function () {
clearInterval(interval);
$(this).css("background-image", "none");
});
jsFiddle of a similar concept (with background colours).
It should be clear enough to see what's going on. Basically we start looping over the images and setting them as the background image on mouse over, and reset it when the mouse leaves.
You can use a library like jQuery-Keyframes
to generate new keyframes at runtime if that is what you are after.
I have a gif image that I want to stretch by making the height and/or width variable. However, I want the image stretching to be done at a speed I set, so it is progressive and visible as it occurs on the screen. The code below works, but it renders the image immediately as a complete image, with no stretching visible. So I thought: insert some kind of timer function to slow down the execution of the "stretching" code. I have tried setTimeout and setInterval (using 1/100 sec delays), but I have not been able to make either work. What am I doing wrong here guys?
$(window).load(function(){
setInterval(function(){
var i=1;
for (i;i<400;i++) {
$("#shape1").html('<img src="image.gif" width="'+i+'" height="40">');
}
},10);
});
The problems with your code are that
at each interval iteration, you repeat the whole for loop
you never stop the interval looping
You may fix your existing code like this :
var i=1;
function step() {
$("#shape1").html('<img src="image.gif" width="'+i+'" height="40">');
if (i++<400) setTimeout(step, 10);
}
step();
Instead of replacing the #shape1 content each time, you could also simply change the width :
var i=1;
var $img = $('<img src="image.gif" width=1 height="40">').appendTo('#shape1');
function step() {
$img.css('width', i);
if (i++<400) setTimeout(step, 10);
}
step();
Demonstration
But jQuery has a very convenient animate function just for this kind of things.
As Dystroy suggested. Use jQuery animate instead
setInterval(function(){
var i=1;
for (i;i<400;i++) {
$("#shape1").animate({
width : i
},10);
}
}, 10);
Here is a jsfiddle
CSS3 transitions are great if your browser supports it.
.resize {
width: 200px;
height: 50px;
transition: width 1s ease;
}
Just add the class to an element to make it stretch out.
img.className = "resize";
css demo
I need help with an animated PNG in Javascript.
I found how to animate a PNG background with Javascript here on Stack Overflow. But my problem is that I only need the animation onmouseover and onmouseout. And the animation should play only once, not in a loop, so when the user moves the mouse over a div the the animation in the background should play once and stop at the last frame, but when the user goes off the div, a reverse animation should play once and stop at the last (first) frame. The script I found here is:
The style:
#anim {
width: 240px; height: 60px;
background-image: url(animleft.png);
background-repeat: no-repeat;
}
The HTML:
<div id="anim"></div>
Javascript:
var scrollUp = (function () {
var timerId; // stored timer in case you want to use clearInterval later
return function (height, times, element) {
var i = 0; // a simple counter
timerId = setInterval(function () {
if (i > times) // if the last frame is reached, set counter to zero
i = 0;
element.style.backgroundPosition = "0px -" + i * height + 'px'; //scroll up
i++;
}, 100); // every 100 milliseconds
};
})();
// start animation:
scrollUp(14, 42, document.getElementById('anim'))
I hope anyone can help me, Thank you
To stop the animation after the first set of frames you do want to change the if condition to not reset the counter to zero but instead to clear the interval and stop it from reoccuring.
To only let it play when you enter an element you can attach the animation function as an event listener and play the whole thing in reverse with another function that you plug into your onmouseout event.
Depending on your target browser and since your question is fairly vague I can recommend two alternatives to you:
Use jQuery animate (all browsers, include ref to jquery)
//Animate to x,y where x and y are final positions
$('#anim').mouseenter(function(e) {
$(this).animate({background-position: x + 'px ' + y + 'px'}, 4200);
})
//Do same for mouseleave
Use a css3 animation (using -webkit browser here)
<style>
#-webkit-keyframes resize {
100% {
height: 123px;
}
}
#anim:hover {
-webkit-animation-name: resize;
-webkit-animation-duration: 4s;
}
I would choose option 2 if you are doing mobile development or can choose only css3 capable browsers.