How to show animated image from PNG image using javascript? [ like gmail ] - javascript

First of all,check out this image
Gmail uses this image to display the animated emoticon.
How can we show such animation using a png image?

I leave you a rough example so you can get a starting point:
I will use a simple div element, with the width and height that the animated image will have, the png sprite as background-image and background-repeat set to no-repeat
CSS Needed:
#anim {
width: 14px; height: 14px;
background-image: url(https://ssl.gstatic.com/ui/v1/icons/mail/im/emotisprites/wink2.png);
background-repeat: no-repeat;
}
Markup needed:
<div id="anim"></div>
The trick is basically to scroll the background image sprite up, using the background-position CSS property.
We need to know the height of the animated image (to know how much we will scroll up each time) and how many times to scroll (how many frames will have the animation).
JavaScript implementation:
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'))
EDIT: You can also set the CSS properties programmatically so you don't have to define any style on your page, and make a constructor function from the above example, that will allow you to show multiple sprite animations simultaneously:
Usage:
var wink = new SpriteAnim({
width: 14,
height: 14,
frames: 42,
sprite: "https://ssl.gstatic.com/ui/v1/icons/mail/im/emotisprites/wink2.png",
elementId : "anim1"
});
var monkey = new SpriteAnim({
width: 18,
height: 14,
frames: 90,
sprite: "https://ssl.gstatic.com/ui/v1/icons/mail/im/emotisprites/monkey1.png",
elementId : "anim4"
});
Implementation:
function SpriteAnim (options) {
var timerId, i = 0,
element = document.getElementById(options.elementId);
element.style.width = options.width + "px";
element.style.height = options.height + "px";
element.style.backgroundRepeat = "no-repeat";
element.style.backgroundImage = "url(" + options.sprite + ")";
timerId = setInterval(function () {
if (i >= options.frames) {
i = 0;
}
element.style.backgroundPosition = "0px -" + i * options.height + "px";
i++;
}, 100);
this.stopAnimation = function () {
clearInterval(timerId);
};
}
Notice that I added a stopAnimation method, so you can later stop a specified animation just by calling it, for example:
monkey.stopAnimation();
Check the above example here.

Take a look at this:
http://www.otanistudio.com/swt/sprite_explosions/
and http://www.alistapart.com/articles/sprites
The answer lies within.

CMS's answer is fine, but there's also the APNG (animated PNG) format that you may want to use instead. Of course the first frame (the one displayed even by browsers that don't support APNG) should be the "ending" frame and just specify to skip the first frame in the file.

Set the background image of an element to the first image, then use javascript to change the image by altering the style every x milliseconds.

You can do it with TweenMax and steppedEase easing : http://codepen.io/burnandbass/pen/FfeAa or http://codepen.io/burnandbass/pen/qAhpj whatever you choose :)

CSS #keyframes can be used in this case
#keyframes smile {
0% { background-postiion: 0 -16px;}
5% { background-postiion: 0 -32px;}
10% { background-postiion: 0 -48px;}
/*...etc*/
}

Related

Trying to transition background image after it's loaded

I'm trying to change the background of my site when a button is clicked with a smooth transition. I understand this requires a pre-load but I'm not sure how to do this.
transition: background-image 3s linear;
js
document.getElementById("loadBG").onclick = function () {
let randomInt = Math.floor(Math.random() * (100 - 1) + 1);
document.getElementById(
"main"
).style.backgroundImage = `url(https://source.unsplash.com/1920x1080/?finland?sig=${randomInt})`;
};
The background-image property you are trying to apply is invalid.
Similarly the nextImage.src source attribute you are trying to apply is invalid as well.
See the code snippet comments for details.
You don't need to create an image node if all you're doing is applying a background-image property.
The Math.random() method can be optimised too (not essential, just a nitpick).
The original code (with console.log feedback) and a working version have been included in the code snippet below:
document.getElementById("loadBG-error").onclick = function() {
const nextImage = new Image();
nextImage.src = `url("https://source.unsplash.com/1920x1080/?finland?sig=${Math.random()}")`;
setTimeout(function() {
document.getElementById("main").style.backgroundImage = nextImage.src;
}, 3000);
console.log('incorrect background-image property url:',nextImage.src);
};
/*
This happens because the image node's (nextImage) src attribute is being
declared with a background-image css property, it starts with "url(... )",
when you have a filepath that doesn't start with a protocol (https://)
the browser will assume it's relative and prepend the current site's domain
to the url, e.g: "https://stacksnippets.net/url(...)".
In addition, the double apostrophes in that string are being ASCII encoded to "%22".
*/
document.getElementById("loadBG-fix").onclick = function() {
let randomInt = Math.floor(Math.random() * (100 - 1) + 1);
setTimeout(function() {
document.getElementById("main").style.backgroundImage = `url(https://source.unsplash.com/1920x1080/?finland?sig=${randomInt})`;
}, 500);
};
/*
If you just need to declare a background-image property for an existing element,
there is no need to create an image node first.
The Math.random() method can be further improved to return a set range(1)
with no floating point value (decimal)(2)
(1) Math.random() * (max - min) + min
(2) Math.floor()
*/
#main {
height: 300px;
width: 100%;
}
<div id="main"></div>
<button id="loadBG-error">Load BG (see error)</button>
<hr>
<button id="loadBG-fix">Load BG (apply fix)</button>
In order to load the image as a backgorund image, the container in which it is located must have a specific height and width. I set a height and width for the # main div.
And you don't need definitions like new image(If you have no other purpose with using new Image) because the src in the img and background url image are different from each other. You can't even those two. Because they work differently.
document.getElementById("loadBG").onclick = function() {
let url = `url("https://source.unsplash.com/1920x1080/?finland?sig=${Math.random()}")`;
setTimeout(function() {
document.getElementById("main").style.backgroundImage = url;
console.log("work")
}, 1000);
};
#main {
width: 100%;
height: 400px;
background-position: center;
background-size: cover;
}
<button type="button" id="loadBG">Click me</button>
<div id="main"></div>

Show a series of images on scroll

The closest solution I found is Show div on scrollDown after 800px.
I'm learning HTML, CSS, and JS, and I decided to try to make a digital flipbook: a simple animation that would play (ie, load frame after frame) on the user's scroll.
I figured I would add all the images to the HTML and then use CSS to "stack them" in the same position, then use JS or jQuery to fade one into the next at different points in the scroll (ie, increasing pixel distances from the top of the page).
Unfortunately, I can't produce the behavior I'm looking for.
HTML (just all the frames of the animation):
<img class="frame" id="frame0" src="images/hand.jpg">
<img class="frame" id="frame1" src="images/frame_0_delay-0.13s.gif">
CSS:
body {
height: 10000px;
}
.frame {
display: block;
position: fixed;
top: 0px;
z-index: 1;
transition: all 1s;
}
#hand0 {
padding: 55px 155px 55px 155px;
background-color: white;
}
.frameHide {
opacity: 0;
left: -100%;
}
.frameShow {
opacity: 1;
left: 0;
}
JS:
frame0 = document.getElementById("frame0");
var myScrollFunc = function() {
var y = window.scrollY;
if (y >= 800) {
frame0.className = "frameShow"
} else {
frame0.className = "frameHide"
}
};
window.addEventListener("scroll", myScrollFunc);
};
One of your bigger problems is that setting frame0.className = "frameShow" removes your initial class frame, which will remove a bunch of properties. To fix this, at least in a simple way, we can do frame0.className = "frame frameShow", etc. Another issue is that frame0 is rendered behind frame1, which could be fixed a variety of ways. ie. Putting frame0's <img> after frame1, or setting frame0's CSS to have a z-index:2;, and then setting frame0's class to class="frame frameHide" so it doesn't show up to begin with. I also removed the margin and padding from the body using CSS, as it disturbs the location of the images. I have made your code work the way I understand you wanted it to, here is a JSFiddle.
It depends on your case, for example, in this jsFiddle 1 I'm showing the next (or previous) frame depending on the value of the vertical scroll full window.
So for my case the code is:
var jQ = $.noConflict(),
frames = jQ('.frame'),
win = jQ(window),
// this is very important to be calculated correctly in order to get it work right
// the idea here is to calculate the available amount of scrolling space until the
// scrollbar hits the bottom of the window, and then divide it by number of frames
steps = Math.floor((jQ(document).height() - win.height()) / frames.length),
// start the index by 1 since the first frame is already shown
index = 1;
win.on('scroll', function() {
// on scroll, if the scroll value equal or more than a certain number, fade the
// corresponding frame in, then increase index by one.
if (win.scrollTop() >= index * steps) {
jQ(frames[index]).animate({'opacity': 1}, 50);
index++;
} else {
// else if it's less, hide the relative frame then decrease the index by one
// thus it will work whether the user scrolls up or down
jQ(frames[index]).animate({'opacity': 0}, 50);
index--;
}
});
Update:
Considering another scenario, where we have the frames inside a scroll-able div, then we wrap the .frame images within another div .inner.
jsFiddle 2
var jQ = $.noConflict(),
cont = jQ('#frames-container'),
inner = jQ('#inner-div'),
frames = jQ('.frame'),
frameHeight = jQ('#frame1').height(),
frameWidth = jQ('#frame1').width() + 20, // we add 20px because of the horizontal scroll
index = 0;
// set the height of the outer container div to be same as 1 frame height
// and the inner div height to be the sum of all frames height, also we
// add some pixels just for safety, 20px here
cont.css({'height': frameHeight, 'width': frameWidth});
inner.css({'height': frameHeight * frames.length + 20});
cont.on('scroll', function() {
var space = index * frameHeight;
if (cont.scrollTop() >= space) {
jQ(frames[index]).animate({'opacity': 1}, 0);
index++;
} else {
jQ(frames[index]).animate({'opacity': 0}, 0);
index--;
}
});
** Please Note that in both cases all frames must have same height.

How to get width from animated div in jQuery

Thanks in advance for your support here. I have a simple code here but I wonder why it doesn't work.
This code below was put into a variable "percent"
var percent = $('#div').animate({width:80 + '%'},1000);
and I want to use the variable to become a text or content to a specific div. I tried to do it this way, however it doesn't work.
$('#val').text(percent); or $('#val').html(percent);
I tried to use the parseInt() function from JavaScript, but it doesn't work as well.
$('#web-design').text(parseInt(percent));
Do you have any suggestions or is this possible?
I am not sure if the line code it is correct
var percent = $('#div').animate({width:80 + '%'},1000);
To find the with property for #div I will do something like this
$('#val').text($("#div").css("width"))
or
$('#val').text($("#div").width())
The animate function does not return the changes to the element. To get the width you will have to use .width() but you will get it in pixel and not percentage.
var width = $('#div').width();
You can try this code:
$('#div1').animate({width:80 + '%'},{
duration:1000,
easing:'swing',
step: function() { // called on every step
$('#div1').text(Math.ceil($('#div1').width()/$('#div1').parent().width()*100) + "%");
}
});
This will print the Div-Width % as text in Div at every step of update.
You code is going to animate to 80% width in 1 second (1000 ms). You can increase the percentage width by 1% each iteration and update your #val at the same time until you hit 80. Below is the example based on 10000ms (10 secs), you can change the starting parameters such as duration, endWidth, startWidth to suit.
Demo: http://jsfiddle.net/zthaucda/
HTML:
<div class="my-anim-div"></div>
<button class="start-animating">Start animation</button>
<div id="val">Width will display here</div>
CSS:
.my-anim-div {
width:0%;
height:200px;
background-color:red;
}
Javascript including jQuery library:
var duration = 10000;
var endWidth = 80;
var startWidth = 0;
$('.start-animating').on('click', function () {
// work out the interval to make the animation in `duration`
var interval = duration / (endWidth - startWidth);
console.log(interval);
var myInterval = setInterval(function () {
// Increment the startWidth and update the width of the div and the display
startWidth++
// update div width
$('.my-anim-div').animate({
'width': startWidth + '%'
}, interval);
// update display
$('#val').text(startWidth + '%');
if (startWidth == 80) {
// then exit the interval
clearInterval(myInterval);
}
}, interval);
});
If you mean you want to get the current width of the div you can use clientWidth property:
$('#div')[0].clientWidth

Decrease image size automatically over a certain amount of time

I am looking for a script but I'm not sure what to look for.
I have a webpage that has the body tag with a background image.
body {
background: url(eye.gif)repeat;
background-size:91px 91px;
}
What I am hoping to achieve is when the page loads it shows the background image as 991px then slowly decrease by 10px over a set time until the original size of 91px.
I'm not sure if there is away to do this, or even another way that when the page is loaded it is zoomed in and then zooms out automatically over time.
Basically when the page is loaded you will see the image twice and then over time you will see more and more.
Can anyone point me in the right direction.
if you use background-size your using css3 and so you can use keyframes
no javascript needed.
#-webkit-keyframes bganimation{
0%{background-size:991px 991px;}
100%{background-size:91px 91px;}
}
body{
background: url(eye.gif)repeat;
background-size:91px 91px;
-webkit-animation:bganimation 20s linear; // 20s = 20 seconds
}
for more support you need to add the other specific prefixes (-moz,-ms..)
Here is a sample using JQuery:
http://jsfiddle.net/frUvf/16/
$(document).ready(function(){
$('body').animate({'background-size':'10000px'}, 50000);
})
Using vanilla JS:
var lowerBound = 250,
step = 10,
duration = 1000,
image = document.getElementById('image');
(function resizer () {
if (image.clientWidth > lowerBound) {
image.style.width = image.clientWidth - step + 'px';
var timer = setTimeout(resizer, duration);
} else {
clearTimeout(timer);
}
}());
Just change the lowerBound/step/duration variables to whatever you need them to be.
Fiddle
with jquery:
var body = $('body');
var zoom = 2;
var interval_zoom = 0.5;
var time_interval = 90000;
setInterval(function(){
body.css("zoom", zoom);
zoom = zoom - interval_zoom;
if(zoom<=1)
clearTimeout(this);
}, time_interval )
Zoom and interval must be calculated
You could use Javascript for the animation or could take a look at CSS3 Transformations: http://web.archive.org/web/20180414114433/http://www.pepe-juergens.de/2013/02/css3-transform/

How to change Fancybox preloader image?

I want replace default Fancybox1.3.4 image preloader (fancy_loading.png) with another preloader.
The Fancybox preloader coded not only in css, but also in javascript itself.
Seems, there are two places in javascript, at least:
_animate_loading = function() {
if (!loading.is(':visible')){
clearInterval(loadingTimer);
return;
}
$('div', loading).css('top', (loadingFrame * -40) + 'px');
loadingFrame = (loadingFrame + 1) % 12;
};
and
$.fancybox.showActivity = function() {
clearInterval(loadingTimer);
loading.show();
loadingTimer = setInterval(_animate_loading, 66);
};
$.fancybox.hideActivity = function() {
loading.hide();
};
So customizing the preloader will require modifying javascript too.
How can I change fancybox-1.3.4 javascript to set custom preloader image?
The CSS declaration is here:
#fancybox-loading div {
position: absolute;
top: 0;
left: 0;
width: 40px;
height: 480px;
background-image: url('fancybox.png');
}
They are using a sprite for the background image and changing the background-position to animate it. If you're going to use a loading.gif image, then you won't need to animate it.
You need to change the background-image path, height, and width to cater to your new image. You may want to comment out their JS code for the animation so that it doesn't conflict.
The loading div is being declared here:
$('body').append(
tmp = $('<div id="fancybox-tmp"></div>'),
loading = $('<div id="fancybox-loading"><div></div></div>'),
overlay = $('<div id="fancybox-overlay"></div>'),
wrap = $('<div id="fancybox-wrap"></div>')
);
You can either piggyback on the loading variable or simply change the styling on #fancybox-loading. You'll then need to remove any reference to loadingTimer and loadingFrame. Comment out this entire function:
/*_animate_loading = function() {
if (!loading.is(':visible')){
clearInterval(loadingTimer);
return;
}
$('div', loading).css('top', (loadingFrame * -40) + 'px');
loadingFrame = (loadingFrame + 1) % 12;
};*/
Modify the following function:
$.fancybox.showActivity = function() {
//clearInterval(loadingTimer);
loading.show();
//loadingTimer = setInterval(_animate_loading, 66);
};
That should do it. You don't want loading to have any setInterval on it since you won't be animating it, but you do want it to hide/show conditionally.
There are two options -
1) Upgrade to v2 as it is now using animated gif
2) Ĺ–eplace showActivity and hideActivity methods with yours, e.g., after including js file -
$.fancybox.showActivity = function() {
/* Add your animated gif to page ... */
}
You dont need to change so much just in js file comment some lines:
$.fancybox.showActivity = function() {
//clearInterval(loadingTimer);
loading.show();
//loadingTimer = setInterval(_animate_loading, 66);
};
Thats all and it will work, but remember change in correct file because where are jquery.fancybox-1.3.4.js and jquery.fancybox-1.3.4.pack.js

Categories

Resources