Two animations run the same time jquery - javascript

I have tried to make two squares move at the same time...
I know the first animation is repeating to infinite but what should i do?
JsFiddle

Both of the other solutions are correct, but please, PLEASE don't make your code a list of if else conditions with a massive inside block. Consider, instead the following solution:
http://jsfiddle.net/NM78r/
$(document).ready(function(){
animateTheBox('block1',0);
animateTheBox('block2',2);
});
function animateTheBox(block,i) {
var animation = {};
var duration = 3000;
var easing = 'linear';
var done = function(){ animateTheBox(block, (i+1)%4); };
switch(i){
case 0: animation = {'left' : "-=100px"}
break;
case 1: animation = {'top' : "-=100px"}
break;
case 2: animation = {'left' : "+=100px"}
break;
case 3: animation = {'top' : "+=100px"}
break;
default: return; //This is so you can't call the function in weird ways, as before.
}
$('.' + block).animate(animation, duration, easing, done);
}
Use a switch statement to determine what kind of animation to do, then only write the actual animation call once. This kind of abstraction is easier to read, and has the added benefit of being way more maintainable. You can be sure that your animation will be done the same way every single time.
EDIT:
Though the above design pattern is probably better in the long run, you could easily do this with an array instead:
$(document).ready(function(){
animateTheBox('block1',0);
animateTheBox('block2',2);
});
function animateTheBox(block,i) {
var animations = [
{'left' : "-=100px"}
, {'top' : "-=100px"}
, {'left' : "+=100px"}
, {'top' : "+=100px"}
];
var duration = 3000;
var easing = 'linear';
var done = function(){ animateTheBox(block, (i+1)%4); };
if ( i < 0 || i >= animations.length)
return; //Don't deal with out of bound numbers.
$('.' + block).animate(animations[i], duration, easing, done);
}
http://jsfiddle.net/4S6Mg/1/
And actually, this could make multi step animation abstraction really easy:
$(document).ready(function(){
var block1Steps = [
{'left' : "-=100px"}
, {'top' : "-=100px"}
, {'left' : "+=100px"}
, {'top' : "+=100px"}
];
var block2Steps = [
{'left' : "+=100px"}
, {'top' : "+=100px"}
, {'left' : "-=100px"}
, {'top' : "-=100px"}
];
multiAnimate($('.block1'), block1Steps, 3000, 'linear', true);
multiAnimate($('.block2'), block2Steps, 3000, 'linear', true);
});
function multiAnimate(item, animations, duration, easing, infinite){
var i = -1;
var step = function(){
i++;
if (infinite)
i %= animations.length;
if (i >= animations.length) return;
item.animate(animations[i], duration, easing, step);
};
step();
}
http://jsfiddle.net/jp2K4/
Then, if you wanted to get REALLY Apeshit, you could give each animation its own duration and easing, and BAM! You've basically created for yourself a little arbitrary multistep animation library.
function multiAnimate(item, animations, duration, easing, infinite){
var defaultDuration = 1000;
var defaultEasing = 'linear';
var i = -1;
var step = function(){
i++;
if (infinite)
i %= animations.length;
if (i >= animations.length) return;
item.animate(animations[i].animation
, (animations[i].duration)? animations[i].duration: defaultDuration
, (animations[i].easing)? animations[i].easing: defaultEasing
, step
);
};
step();
}
$(document).ready(function(){
var block1Steps = [
{
animation: {'left' : "-=100px"}
, duration: 3000
, easing: 'linear'
}
, {
animation: {'top' : "-=100px"}
, duration: 1000
, easing: 'swing'
}
, {
animation: {'left' : "+=100px"}
, duration: 5000
, easing: 'swing'
}
, {
animation: {'top' : "+=100px"}
, duration: 2000
, easing: 'linear'
}
];
var block2Steps = [
{
animation: {'left' : "+=100px"}
, duration: 5000
, easing: 'swing'
}
, {
animation: {'top' : "+=100px"}
, duration: 2000
, easing: 'linear'
}
, {
animation: {'left' : "-=100px"}
, duration: 3000
, easing: 'linear'
}
, {
animation: {'top' : "-=100px"}
, duration: 1000
, easing: 'swing'
}
];
multiAnimate($('.block1'), block1Steps, 3000, 'linear', true);
multiAnimate($('.block2'), block2Steps, 3000, 'linear', true);
});
http://jsfiddle.net/nnQU8/

The reason is you need to wait for the first animation to complete before telling the box to begin the next set of animation. In your code, you're not giving the red box a chance to begin animating because the yellow one is constantly doing it (there is a closure created by the animateTheBox and both boxes are calling it) :)
So I added the complete function handler to your .animate() and moved the animateTheBox() call into there.
See: http://jsfiddle.net/DkmKA/

You need to use the completion function of each animation to start the next animation like this:
$(document).ready(function(){
animateTheBox('block1',0);
animateTheBox('block2',2);
});
function animateTheBox(block,i) {
if (i==0)
{
$('.'+block).animate({'left' : "-=100px"}, 3000, 'linear', function() {
animateTheBox(block,1);
});
}
else if (i==1)
{
$('.'+block).animate({'top' : "-=100px"}, 3000, 'linear', function() {
animateTheBox(block,2);
});
}
else if (i==2)
{
$('.'+block).animate({'left' : "+=100px"}, 3000, 'linear', function() {
animateTheBox(block,3);
});
}
else if (i==3)
{
$('.'+block).animate({'top' : "+=100px"}, 3000, 'linear', function() {
animateTheBox(block,0);
});
}
}
Working demo: http://jsfiddle.net/jfriend00/39SUN/
In the spirit of DRY, here's a much shorter way of doing it:
$(document).ready(function(){
animateTheBox('.block1',0);
animateTheBox('.block2',2);
});
function animateTheBox(block,i) {
var anims = [
{left: "-=100px"},
{top: "-=100px"},
{left: "+=100px"},
{top: "+=100px"},
];
$(block).animate(anims[i], 3000, 'linear', function() {
animateTheBox(block,(i+1) % 4);
});
}
Working demo: http://jsfiddle.net/jfriend00/nKuGs/

Related

StaggerTo animation

I'm trying to do a cascade animation on a video banner using staggerTo but it is not working. I want cascade animation on banner expand click. my code is
function FullscreenClick(e){
ADTECH.expand();
ADTECH.registerVideoPlayer(videoBGPlayer , 'VideoExpanded');
videoBGPlayer.removeEventListener('timeupdate',timeCheck,false);
TweenLite.to(wrapper , 1 , { height: 546 });
TweenLite.staggerTo( videoBGPlayer , 1 , {bottom:"+=150", ease:CubicIn.ease}, 0.2);
TweenLite.to( audioOn , 0.4 , { opacity: 1 } );
fullscreenButton.style.visibility = 'hidden';
fomButton.style.visibility = 'visible';
videoBGPlayer.load();
videoBGPlayer.play();
videoBGPlayer.muted = false;
closeButton.style.visibility = 'visible';
window.parent.postMessage('ExpandCreative', '*');
expanded = true;
}
thanks
Assuming Elastic is the type of effect you would like, then the code below should work. Other easing effects and config can be found at GSAP documentation
function FullscreenClick(e){
ADTECH.expand();
ADTECH.registerVideoPlayer(videoBGPlayer , 'VideoExpanded');
videoBGPlayer.removeEventListener('timeupdate',timeCheck,false);
TweenLite.to(wrapper , 1 , { height: 546 });
TweenLite.to( videoBGPlayer , 1 , {bottom:"+=150", ease: Elastic.easeOut.config(1, 0.3)});
TweenLite.to( audioOn , 0.4 , { opacity: 1 } );
fullscreenButton.style.visibility = 'hidden';
fomButton.style.visibility = 'visible';
videoBGPlayer.load();
videoBGPlayer.play();
videoBGPlayer.muted = false;
closeButton.style.visibility = 'visible';
window.parent.postMessage('ExpandCreative', '*');
expanded = true;
}

Animated clouds and plane

I have been created a simple apps, with a lot of Javascript code, I use jQuery too and the code looks so dirty. So now, I want to try restructure my code to Object-Oriented. What I've confused is where to call a properties, where to put an user action to an element, where to put dom element variable, etc. It's a bit of my code before and after restructure.
Before:
var $cloud = $(".js-cloud");
var $plane = $(".js-plane");
function randomPosition(min, max) {
return Math.random() * (max - min) + min;
}
$cloud.each(function(){
var leftPosition = randomPosition(1,100) + "%";
$(this).css("left",leftPosition)
var speed = $(this).data("speed");
$(this).velocity({
left : "-200px"
}, {
duration : speed,
easing : "linear",
loop : true
})
})
function loopPlane(){
$plane.velocity({
left : "-300px"
}, {
duration : 7000,
easing : "linear",
complete : function(){
$(this).css({
"right" : "-300px",
"left" : "auto"
})
loopPlane()
},
delay : 15000
})
}
loopPlane()
After:
//Clouds and plane element
var $cloud = $(".js-cloud");
var $plane = $(".js-plane");
/* Module */
var background = {
init : function(){
this.loopClouds();
this.loopPlane();
},
randomPosition : function(min,max){
return Math.random() * (max - min) + min;
},
loopPlane : function(){
var obj = this;
//Animate it
$plane.velocity({
left : "-300px"
}, {
duration : 7000,
easing : "linear",
complete : function(){
$plane.css({
"right" : "-300px",
"left" : "auto"
})
obj.loopPlane()
},
delay : 1000
})
},
loopClouds : function(){
var obj = this;
$cloud.each(function(){
var leftPosition = obj.randomPosition(1,100) + "%";
$(this).css("left",leftPosition)
var speed = $(this).data("speed");
//Animate it
$(this).velocity({
left : "-200px"
}, {
duration : speed,
easing : "linear",
loop : true
})
})
}
}
Is that my code look cleaner and readable? or there is a better version of my restructure code?
When you use $var.each, should you not be using the first parameter of the callback to target elements, instead of using this to target the $var array. If it's anything like a .forEach (but with an fn.init array), then the element is passed through the callback into the context of the loop.
You do this:
function loopClouds() {
var obj = this;
$cloud.each(function(){
var leftPosition = obj.randomPosition(1,100) + "%";
$(this).css("left",leftPosition)
var speed = $(this).data("speed");
//Animate it
$(this).velocity({
left : "-200px"
}, {
duration : speed,
easing : "linear",
loop : true
})
});
}
Shouldn't you be doing this?
function loopClouds() {
$cloud.each(function (cloud) {
cloud.css("left", randomPosition(1, 100));
cloud.velocity({left: "-200px"}, {
duration: cloud.data("speed"),
easing: "linear",
loop: true
});
});
}
This is just one example, but your usage of the this keywords seems to be a bit shoddy all-round.

Trying to change which animations to play based on variable value

So I am trying to basically create a div that slides out using transforms, as those work best in Chrome. I'm using a plugin called Animo.js that uses .css classes to animate using jquery, but I can't seem to get my code right. I'd rather not use class toggles or jquery toggles of any sort.
Code example
$(document).ready(function()
var $hTog = 0
$('#home').click(function()
{
if( $hTog.val() == 0)
{
$('#hSlider').animo({animation: 'hGrow', iterate: 1, duration: 10, keep: true, timing: 'linear'});
$hTog.val() == 1;
};
else
{
$('#hSlider').animo({animation: 'hShrink', iterate: 1, duration: 10, keep: true, timing: 'linear'});
$hTog.val() == 0;
};
})
})
Thanks in advance guys.
There are several things you can do in your code try this:
$(document).ready(function(){ // the '{' not there add this
var $hTog = 0;
$('#home').click(function(){
if( $hTog == 0){
$('#hSlider').animo({animation: 'hGrow', iterate: 1, duration: 10, keep: true, timing: 'linear'});
$hTog = 1;
}else{
$('#hSlider').animo({animation: 'hShrink', iterate: 1, duration: 10, keep: true, timing: 'linear'});
$hTog = 0;
}
});
});
Remove .val() from the if conditions.
Remove the ; from the closing of if condition and else part too.
Also after the .animo() method runs update the value of var with removing .val() and you don't need == to update the values.
You are referencing .val(), but you assigned $hTog the value 0, without properties. Try this:
$(document).ready(function() {
var hTog = 0
$('#home').click(function() {
if (hTog === 0) {
$('#hSlider').animo({animation: 'hGrow', iterate: 1, duration: 10, keep: true, timing: 'linear'});
hTog = 1;
}
else {
$('#hSlider').animo({animation: 'hShrink', iterate: 1, duration: 10, keep: true, timing: 'linear'});
hTog = 0;
}
});
});

Autoscrolling slide javascript

I have This javascript code for a slider that I downloaded , and can't figure out how to make it auto scrolling !!
I actually downloaded this code from http://tympanus.net/Tutorials/FullscreenSlitSlider/index2.html
It actually don't contain a next button so i can add an interval like the other sliders :(
$(function() {
var Page = (function() {
var $nav = $( '#nav-dots > span' ),
slitslider = $( '#slider' ).slitslider( {
onBeforeChange : function( slide, pos ) {
$nav.removeClass( 'nav-dot-current' );
$nav.eq( pos ).addClass( 'nav-dot-current' );
}
} ),
init = function() {
initEvents();
setInterval(initEvents,1000);
},
initEvents = function() {
$nav.each( function( i ) {
$( this ).on( 'click', function( event ) {
var $dot = $( this );
if( !slitslider.isActive() ) {
$nav.removeClass( 'nav-dot-current' );
$dot.addClass( 'nav-dot-current' );
}
slitslider.jump( i + 1 );
return false;
} );
} );
};
return { init : init };
})();
Page.init();
});
Like it says in the docs (Google is helpful):
slitslider = $( '#slider' ).slitslider({
autoplay : true
});
should do it.
If you don't want to read the whole thing, here's a short list of common config options:
$.Slitslider.defaults = {
// transitions speed
speed : 800,
// if true the item's slices will also animate the opacity value
optOpacity : false,
// amount (%) to translate both slices - adjust as necessary
translateFactor : 230,
// maximum possible angle
maxAngle : 25,
// maximum possible scale
maxScale : 2,
// slideshow on / off
autoplay : false,
// keyboard navigation
keyboard : true,
// time between transitions
interval : 4000,
// callbacks
onBeforeChange : function( slide, idx ) { return false; },
onAfterChange : function( slide, idx ) { return false; }
};

Script doesn't work on elements loaded with infinite scrolling

I'm using this script on my tumblr page, which gives posts different random text colors:
function get_random_color() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;}
$(function() {
$(".post").each(function() {
$(this).css("color", get_random_color());
}); });
The thing is the script isn't working for elements loaded with infinite scrolling. Can anyone help me rewrite this code? I don't know how to write javascript sadly.
Take a look at your blog's main.js script. You can call your custom function when you grab the new elements from another page. This is my proposed revision of your main.js file.
$(window).load(function () {
var $wall = $('#content');
$wall.imagesLoaded(function () {
$wall.masonry({
itemSelector: '.post',
isAnimated: false
});
});
$wall.infinitescroll({
navSelector: '#pagination',
nextSelector: '#pagination li a.pagination_nextlink',
itemSelector: '.post',
loadingImg: "http://static.tumblr.com/kwz90l7/bIdlst7ub/transparent.png",
loadingText: " ",
donetext: " ",
bufferPx: 100,
debug: false,
errorCallback: function () {
$('#infscr-loading').animate({
opacity: .8
}, 2000).fadeOut('normal');
}
}, function (newElements) {
var $newElems = $(newElements);
$newElems.hide();
$newElems.each(function(value){
value.css("color", get_random_color());
});
$newElems.imagesLoaded(function () {
$wall.masonry('appended', $newElems, {
isAnimated: false,
animationOptions: {
duration: 900,
easing: 'linear',
queue: false
}
}, function () {
$newElems.fadeIn('slow');
});
});
$(document).ready(function () {
$("a[rel^='prettyPhoto']").prettyPhoto({
deeplinking: false,
default_width: 600,
default_height: 550,
allow_resize: true,
});
});
});
$('#content').show(500);
});
function get_random_color() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
What I've done is add your get_random_color function and called it from within the Infinite Scroll call to add a custom color to each of the elements in $newElems so really, all I've done is taken your code and integrated it differently than what you were trying to do, which wasn't working. This should, theoretically, work. If it doesn't or you have questions, let me know.

Categories

Resources