Function to animate progress bar based on another function - javascript

Given a function with parameters in an array, where the first number is the delay time, and the width property is how much to fill the bar by:
var barFill = new AnimationSequence(bar, [
[100, { width: '10%' }],
[200, { width: '20%' }],
[200, { width: '50%' }],
[200, { width: '80%' }],
[300, { width: '90%' }],
[100, { width: '100%' }]
]);
barFill.animate();
I'm trying to write a function to take those two parameters and animate the filling of the progress bar. So far I have this function:
function AnimationSequence() {
var elem = document.getElementById("myBar");
var width = 10;
var id = setInterval(frame, 10);
function frame() {
if (width >= 100) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
document.getElementById("label").innerHTML = width * 1 + '%';
}
}
}
This is the current JSFIDDLE: link

Ok... whats wrong with Your code:
You defined onclick in html - please don't do that. Use JS to attach listeners
You are firing 'showProgress' which doesn't exist
You are using 'new' operator. You should only use it when You want to create new instance of given 'class' (JS has no real classes), and in this case - You just want to execute function.
You are using setInterval when what You really want is setTimeout (or at least I think so)
You want to animate elements without requestAnimationFrame - well it's basically bad idea, but You can do that.
I'm attaching fiddle, which does what You wanted (or at least I think so), but be aware that such a simple thing should have been done with CSS. If You do not care about actual progress of process, and You just want to show user an progress bar, than use CSS transition (I've already done it in snippet), and trigger class which will set width to 100%, on button click.
Theres fiddle for You.
.

Related

Scale an absolutely positioned div from center

I have a number of divs positioned absolutely on a background image.
On the page will also be some buttons. When those are clicked different variables will trigger, shrinking and growing these divs.
Here is the javascript I'm currently using...
$(document).ready(function() {
var title = 1;
$(".button1").click(function() {
title = 1;
});
$(".button2").click(function() {
title = 2;
});
$(document).click(function(e) {
console.log(title);
if (title==1){
$('.london').animate({ backgroundColor:'green', width:'50', height:'50' }, 300);
} else if (title==2){
$('.london').animate({ backgroundColor:'red', width:'40', height:'40' }, 300);
}
});
});
As they are absolutely positioned they are scaled from the corner they are positioned with.
see an example here.
What I need to do is shrink and grow these divs from their center point. The only solutions I've seen seem overly complicated.
I guess I could add a negative margin of half the divs width in the jQuery to counteract this? I'll try that if there are no better solutions
Thanks for any help.
bboybeatle, your "negative margin of half the divs width" idea is spot on, and not at all difficult to implement. Just include the required marginTop and marginLeft settings in the two animations.
$(function() {
var cssMap1a = {
backgroundColor: 'green'
};
var cssMap1b = {
width: 50,
height: 50,
marginTop: -10,
marginLeft: -10
};
var cssMap2a = {
backgroundColor: 'red'
};
var cssMap2b = {
width: 30,
height: 30,
marginTop: 0,
marginLeft: 0
};
$(".button1").click(function () {
$('.london').css(cssMap1a).animate(cssMap1b, 300);
});
$(".button2").click(function () {
$('.london').css(cssMap2a).animate(cssMap2b, 300);
});
});
And here's a fiddle. Fiddles are not difficult to set up. Hopefully this will help you next time you need to ask a question here.
As you will see :
"London" and the buttons are moved to a better position for demo purposes
The colour changes are separated out as separate css maps. They didn't work in the fiddle when included in the animation maps. jQuery needs a plugin to animate colours.
Thanks very much for that #Roamer-1888, I actually used some variables to make it slightly easier to apply the margin. I will remember that technique of putting multiple css properties in a variable..
Heres a snippet of my code I ended up using...
londonMargin = london/2 - london;
$('.london').animate({ width:london, height:london, marginLeft:londonMargin, marginBottom:londonMargin }, 300);
Just for fun I put together a little FIDDLE that has a function to which you pass an element name, the x and y coordinates of the center, and it will position the element in the larger element.
JS
var myelement = $('.boxdiv');
var myelement2 = $('.boxdiv2');
putmycenter( myelement, 90, 90 );
putmycenter( myelement2, 160, 280 );
function putmycenter (element, x, y)
{
var boxdivxcentre = element.width()/2;
var boxdivycentre = element.height()/2;
var boxdivposx = (x - boxdivxcentre);
var boxdivposy = (y - boxdivycentre);
element.css({
"top" : boxdivposy + 'px',
"left" : boxdivposx + 'px'
});
}

Doing something on second click with Snap.svg

I am writing a basic code for an animation on click with Snap.svg. It looks like this:
var s = Snap(500, 500);
var circle = s.rect(100,100,100,100);
circle.click(function(){
var width = circle.attr('width');
var height = circle.attr('height');
circle.animate({
width: width/2,
height :height/2
}, 2000);
});
I make a rectangle in the top left corner of the container and animate it's width on a click. THEN, however, I want to do something different on the second click, return it to its original state for example.
I'd also be glad to learn how do you handle this second click in Javascript in general.
For example: press this button once and the slide navigation opens. Tap it second time and the navigation dissappears.
Thanks in advance!
You can do that by using the event.detail property. In your case, that would be:
circle.click(function(e) {
var width = circle.attr('width');
var height = circle.attr('height');
if (e.detail == 1) {
circle.animate({
width: width/2,
height :height/2
}, 2000);
} else if (e.detail == 2) {
circle.animate({ //example
width:width,
height:height
}, 2000);
}
});
There, the animation to change back to the original sizes plays when the user performs a double click (so 2x fast). If you basically want to toggle the element, instead of reverting it on doubleclick, you can simply check if the element has a width or height style other than its initial width or height:
circle.click(function(e) {
var width = circle.attr('width');
var height = circle.attr('height');
if (parseInt(this.style.width) == parseInt(width) || !this.style.width) {
circle.animate({
width: width/2,
height :height/2
}, 2000);
} else {
circle.animate({ //example
width:width,
height:height
}, 2000);
}
});
Then the if() will return true when either the width attribute is equal to the width style, or when the width style is empty/not defined.
You'd want to store what state of the click.
There are many different ways to go about this, but I'll choose two:
Create a counter variable (say, counter) and increment it each time the click handler runs. Then, each time, to decide what to do, see if the number is even or odd:
var counter = 0;
circle.click(function(){
if(counter % 2 == 0){
//action1
}else{
//action2
}
counter++;
});
Alternatively, you can use a Boolean that changes each time to keep track of which action to perform.
var flag = true;
circle.click(function(){
if(flag){
//action1
flag = false;
}else{
//action2
flag = true;
}
});

Slide boxes with margin-left check if overslided

I made a simple content/box slider which uses the following javascript:
$('#left').click(function () {
$('#videos').animate({
marginLeft: '-=800px'
}, 500);
});
$('#right').click(function () {
$('#videos').animate({
marginLeft: '+=800px'
}, 500);
});
Here is the demo: http://jsfiddle.net/tjset/2/
What I want to do and I can't figure out how to show and hide arrows(left and right box) as the all the boxes slided.
So I clicked 4 time to the LEFT and slided all the boxes! then hide "left" so that you can't give more -800px
What can I do?
What you can do is check after the animation completes to see if the margin-left property is smaller or larger than the bounds of the video <div>. If it is, depending on which navigation button was clicked, hide the appropriate navigation link.
Check out the code below:
$('#left').click(function () {
// reset the #right navigation button to show
$('#right').show();
$('#videos').animate({
marginLeft: '-=800px'
}, 500, 'linear', function(){
// grab the margin-left property
var mLeft = parseInt($('#videos').css('marginLeft'));
// store the width of the #video div
// invert the number since the margin left is a negative value
var videoWidth = $('#videos').width() * -1;
// if the left margin that is set is less than the videoWidth var,
// hide the #left navigation. Otherwise, keep it shown
if(mLeft < videoWidth){
$('#left').hide();
} else {
$('#left').show();
}
});
});
// do similar things if the right button is clicked
$('#right').click(function () {
$('#left').show();
$('#videos').animate({
marginLeft: '+=800px'
}, 500, 'linear', function(){
var mRight = parseInt($('#videos').css('marginLeft'));
if(mRight > 100){
$('#right').hide();
} else {
$('#right').show();
}
});
});
Check out the jsfiddle:
http://jsfiddle.net/dnVYW/1/
There are many jQuery plugins for this. First determine how many results there are, then determine how many you want visible, then use another variable to keep track with how many are hidden to the left and how many are hidden to the right. So...
var total = TOTAL_RESULTS;
var leftScrolled = 0;
var rightScrolled = total - 3; // minus 3, since you want 3 displayed at a time.
instead of using marginLeft I would wrap all of these inside of a wrapper and set the positions to absolute. Then animate using "left" property or "right". There's a lot of code required to do this, well not MUCH, but since there are many plugins, I think you'd be better off searching jquery.com for a plugin and look for examples on how to do this. marginLeft is just not the way to go, since it can cause many viewing problems depending on what version of browser you are using.

How can I set the duration of this jQuery animation proportionally?

I've created a quick test to show what I'm trying to do:
http://jsfiddle.net/zY3HH/
If you click the "Toggle Width" button once, a square will take one second to grow to full width. Click it again, and it will take one second to shrink down to zero width.
However, click the "Toggle Width" button twice in rapid succession - the second time when the square has grown to only a small fraction of its total width (like 10%) - you'll notice that the animation still takes a full second to return the square to zero width, which looks awkward, IMO.
While that behavior is expected, I'd like the latter animation to happen in an amount of time that's proportional to the width that it's covering. In other words, if you click "Toggle Width" a second time when the square is at 10% of its total width, I'd like it to take about 1/10th of a second to shrink back to zero width.
It should be relatively easy (I think) to make the value of the duration property dynamic, calculated when the jQuery click handler is run, to measure the current width of the square and determine the duration accordingly.
However, am I missing a better way to do this? Does jQuery provide an easy way, or expose some sort of method or property to make this easier?
I don't think jQuery has any built-in utility for doing this. The math required to do what you want is fairly straightforward, however, so I'd suggest just going that route. Something like:
var expanded = false;
$('input').click(function() {
$('div').stop();
var duration;
if (expanded) {
duration = ($('div').width() / 100) * 1000;
$('div').animate({ width: '0' }, { queue: false, duration: duration });
expanded = false;
} else {
duration = ((100 - $('div').width()) / 100) * 1000;
$('div').animate({ width: '100px' }, { queue: false, duration: duration });
expanded = true;
}
});
Here's a working example: http://jsfiddle.net/zY3HH/2/
If you've got some free time on your hands, maybe you could make the duration interpolation logic a bit more generic and package it up as a jQuery extension/plugin.
This is what you want - http://jsfiddle.net/FloydPink/qe3Yz/
var expanded = false;
$('input').click(function() {
var width = $('div').width(); //gives the current width of the div as a number (without 'px' etc.)
if (expanded) {
$('div').animate({
width: '0'
}, {
queue: false,
duration: (width/100 * 1000)// (current width/total width * 1 sec in ms) });
expanded = false;
} else {
$('div').animate({
width: '100px'
}, {
queue: false,
duration: 1000
});
expanded = true;
}
});

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

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*/
}

Categories

Resources