How to animate correctly a GSAP menu? - javascript

Holla, I need to reset the animation when I close menu and open it again. How can I do that? Animation works only the first time when I open menu.
CSSPlugin.defaultTransformPerspective = 600;
TweenMax.staggerFrom('ul#menu li', 1.5, {rotationX:-90, transformOrigin:"50% 0%", ease:Elastic.easeOut}, 0.4);
Here is the code: http://codepen.io/hafsadanguir/pen/qOdaab.
Thanks for help!

Is this the kind of result you were after?
JavaScript:
CSSPlugin.defaultTransformPerspective = 600;
var toggleMenu = $('.menu-toggle');
var logo = $('#logo');
var logotitle = $('#logotitle');
var listItems = $('ul#menu li');
var timeline = new TimelineMax({ paused: true, reversed: true });
timeline.fromTo([logo, logotitle], 0.6, { top: 300 }, { top: -50, ease: Power2.easeInOut });
timeline.staggerFromTo(listItems, 1.2, { autoAlpha: 0, rotationX: -90, transformOrigin: '50% 0%' }, { autoAlpha: 1, rotationX: 0, ease: Elastic.easeOut.config(1, 0.3) }, 0.1, 0.3);
toggleMenu.on('click', function() {
$(this).toggleClass('on');
timeline.reversed() ? timeline.play() : timeline.reverse();
});
A few things have changed so here are the details:
First and foremost, I didn't see the need for the hidden class so I have removed it from my solution.
Plus, the on class toggled on the .menu-section element seemed pretty unnecessary as well. I removed it, but kept the properties defined on the .menu-section CSS rule.
On to the fun part, the JavaScript.
You basically needed a TimelineMax to operate upon.
Judging by the imports you had in the JavaScript settings panel, I am assuming that you have some idea of what TimelineMax (and TimelineLite) are all about. By in any case, TimelineLite is about building and managing sequences of TweenLite, TweenMax, TimelineLite, and/or TimelineMax instances and TimelineMax is an extension of TimelineLite, adding more power to it.
So, what happens in the code is that a TimelineMax instance has been initialised, tweens have been added to it and then, upon clicking of the .menu-toggle button element, this timeline is either played or reversed.
The line timeline.reversed() ? timeline.play() : timeline.reverse(); is basically a shortened, fancy version of an if condition and it comes to down to personal preference more than anything else, no performance gain or anything that I am aware of. In a normal if clause, it would have been written like this:
if (timeline.reversed()) { timeline.play(); } else { timeline.reverse(); }.
The condition that is being checked is .reversed() property of timeline. You would notice that while initialising new TimelineMax(...), I set reversed: true property on it. What it does is that after all the tweens are added to timeline, it would behave as if timeline was immediately reversed such that the orientation of the timeline had been flipped. Read more about it in the TimelineMax documentation link I shared above.
The .play() and .reverse() methods are pretty self-explanatory as they make the timeline go forwards or backwards respectively.
That is about it.
Hope this helps.

Related

How do I make an animation run once? -anime.js and waypoints.js

I'm using waypoints.js to see if an element is visible and then I use anim.js to animate it. Works. The problem is that it's running every time I scroll past the element again. I would like the animation to run only one time. I can't really find how I can achieve that. The anime.js documentation is talking about complete() but I don't understand how to use it. Help!
This is what my code looks like:
$('.sequential').waypoint(function() {
var CSStransforms = anime({
targets: this.element,
opacity: [0, 1],
translateY: [50, 0]
});
}, {
offset: '95%'
});

Why is ScrollMagic triggering on page load?

I have a timeline and scene set up with ScrollMagic, and 50% of the time it triggers when the page loads, and not where I have set my trigger to start on a specific div.
My code:
jQuery(document).ready(function($){
// init ScrollMagic Controller.
var controller = new ScrollMagic.Controller();
var fadeAnim;
// Animation 1
fadeAnim = function() {
var timeline = new TimelineMax();
tl1.to('#animateThis1', 1,{ opacity: 1, marginTop: '0%', ease: Power1.easeOut},1)
.to('#animateThis2', 1,{ opacity: 1, marginTop: '3%', ease: Power1.easeOut}, 1.5)
}
new ScrollMagic.Scene({triggerElement: "#trigger", offset: -300})
.setTween(fadeAnim)
.addTo(controller);
Now the frustrating thing is that it works at times and then at other times it starts when the page is finished loading, so that by the time I scroll to #trigger the animation has already completed. Other times it works as expected.
I'm not sure am I missing something, I have searched on Google and my code seems similar to what is needed.
Thanks.
Your code seems to add an offset.Check that.Try using debugging options in Scene or
Try to use addInticator plugin to debug
Try to provide a codepen or plunker for others to check the issue.It is difficult to give a solution based on your current question
I had a similar issue and it was because of a conflict between the version of ScrollMagic and jquery.
For me, using any version of ScrollMagic != 1.3.0 resulted in the error you describe.
It's worth a shot to try using 1.3.0 instead, e.g.
https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/1.3.0/jquery.scrollmagic.js

jQuery and Greensock animations -- animate all elements on screen with classname

I'm trying to animate all elements that match the class "customers" on my page once they are scrolled into view.
My current version:
$(window).on('scroll', function() {
if(!$('.customers').hasClass('animated')) {
if($('.customers').isOnScreen(0.45, 0.45)) {
TweenMax.staggerTo($('.customer'), 0.3, {bottom:"+=50px", opacity:1, ease: Power2.easeOut}, 0.15);
$('.customers').addClass('animated');
}
}
})
Works to animate the first element when it enters the screen, and unfortunately as a result also animates the others while they are offscreen. What I want to happen is that each element that matches "customers" animates when it is scrolled into view.
(note that isOnScreen is a custom function that does element detection within the window).
I've tried using jquery's each function as such:
$(window).on('scroll', function() {
$('.customers').each(function( i ) {
if(!this.hasClass('animated')) {
if(this.isOnScreen(0.45, 0.45)) {
TweenMax.staggerTo($('.customer'), 0.3, {bottom:"+=50px", opacity:1, ease: Power2.easeOut}, 0.15);
this.addClass('animated');
}
}
})
And Ive also tried wrapping each "this" statement as a jquery element as $(this).
I'm getting unexpected behavior in that the elements conitnue to animate as I scroll, even though they should have had their "animated" class removed (I want them to animate only the first time they enter the screen).
What I'm thinking I may need to do is create an array of customers, and then perform the TweenMax to each element in the array, but I'm not sure if this will work.
All right here is what I think you needed to do.
There had to be a listener for the scroll event on the window object to begin with in the first place of course. Stating the obvious.
Then you loop through the .customers elements using an each.
Then you check if each of those .customers elements already have a animated class on them. If, they do, then nothing happens but if they don't, the rest follows.
The current .customers element is then checked if it is in a defined viewport area using the custom function .isonScreen().
Then TweenMax animates .customer elements found within the current .customers element that we are currently looping through. Notice the difference between .customers, the parent element, and the child .cusotmer elements. Remember, we are inside a loop, so each of the .customers element is looped through and then we further try to find .customer elements within each of them. The jQuery that helps us find inner .customer elements is: $(this).find('.customer').
Next up, in your CSS, opacity: 0; line was previously commented out for .customer elements. I uncommented it back on.
We then use .staggerFromTo method of TweenMax to define a set of initial properties to begin our tween with, and end of another set of properties, all with a little bit of stagger between the animations so they don't just come up all the same time, neither do they wait for each other to finish before the next one plays. It is an overlapping animation.
Another thing to note here is that we are animating y property of the elements which is a special property provided by TweenMax which is basically a short-cut to animate translateY(...) property as if you did that using CSS.
Finally, you apply the .animated class on the currently looped .customers element.
JavaScript:
$(window).on('scroll', function() {
$('.customers').each(function() {
if (!$(this).hasClass('animated')) {
if ($(this).isOnScreen(0.45, 0.45)) {
TweenMax.staggerFromTo($(this).find('.customer'), 0.3, {
y: 200,
opacity: 0
}, {
y: 0,
opacity: 1,
ease: Power2.easeOut
}, 0.15);
$(this).addClass('animated');
}
}
});
});
Here is the fiddle. Hope this helps.

Replace div with left-in slide animation

I would like to replace a div's contents with another via a slide animation; the first div slides to the left outside of the box (hidden), whilst the second slides in.
I tried this;
http://jsfiddle.net/DTcHh/1203/
But it does not appear to be doing anything. What am I doing wrong?
var $oldBox = $("#signup .box[data-step=1]");
var $newBox = $("#signup .box[data-step=2]");
var outerWidth = $oldBox.outerWidth(true);
var posSlideOut = (2 > 1 ? -outerWidth : outerWidth);
var posSlideIn = (2 > 1 ? outerWidth : -outerWidth);
$.when($oldBox.animate({left: posSlideOut}, "slow"), $newBox.css("left", posSlideIn + "px").animate({"left": 0}, "slow"));
Here is my update to get the javascript working
jsfiddle
The main changes were that I added the $(document).on('click') event to fire the animation and switched left to margin-left since you are not using relative or fixed positioning
This should get you in the right direction
Update:
Also, I added javascript to remove the "display: hidden;" from your second div
GreenSock Animation Platform (GSAP) with TweenLite / TweenMax. It provides much smoother transitions with far greater customization than jQuery or CSS3 transitions. In order to animate CSS properties with TweenLite / TweenMax, you'll also need their plugin called "CSSPlugin". TweenMax includes this automatically.
First, load the TweenMax library:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
Or the lightweight version, TweenLite:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/easing/EasePack.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenLite.min.js"></script>
Then, call your animation:
var myObj= document.getElementById("myDiv");
// Syntax: (target, speed, {distance, ease})
TweenLite.to(myObj, .7, { x: 500, ease: Power3.easeOut});
You can also call it with an ID selector:
TweenLite.to("#myID", .7, { x: 500, ease: Power3.easeOut});
If you have jQuery loaded, you can use more advanced broad selectors, like all elements containing a specific class:
// This will parse the selectors using jQuery's engine.
TweenLite.to(".myClass", .7, { x: 500, ease: Power3.easeOut});
For full details, see:
TweenLite Documentation
According to their website:
"TweenLite is an extremely fast, lightweight, and flexible animation tool that serves as the foundation of the GreenSock Animation Platform (GSAP)."

How to slide entire webpage?

For example - http://www.tumblr.com
Log out and try to click buttons "Log In", "Sign up", "30 reasons why you'll love Tumblr" (especially interesting).
How to create this slide effect?
P.S: i'm not asking for provide me working code, just guidelines and advices.
UP: seems like i found the possible solution. Code from tumblr js files.
return new Effect.Move(element, {
x: initialMoveX,
y: initialMoveY,
duration: 0.01,
beforeSetup: function(effect) {
effect.element.hide().makeClipping().makePositioned();
},
afterFinishInternal: function(effect) {
new Effect.Parallel(
[ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
new Effect.Scale(effect.element, 100, {
scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
], Object.extend({
beforeSetup: function(effect) {
effect.effects[0].element.setStyle({height: '0px'}).show();
},
afterFinishInternal: function(effect) {
effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
}
}, options)
);
}
You'll find a working demo of a full-page slide here: http://acarna.com/full-page-slide.php
View the source and the CSS as both are requird for this to work. The main keys to note are...
You need a container in which 2 (or more) screen-sized pages are held (#wrapper in my demo)
This container needs to have its overflow property set to hidden
You must detect the screen height each time you run the animation (in case the window size has changed)
Have you check out the scripts and css they have used in their pages?
just check it out you will get the clue how to do it.
I made this effect on my own site too. I don't know how tumblr did that, but I have figured out my own way to do this(for tumblr's effect as an example):
step 1. before redirect to a new url, slide the bottom section up of current page
step 2. slide down the top section when the new url document.ready
Update years later:
Since I just got a new vote-up, I discovered this old answer which is now a little bit outdated.
With modern javascript, you just need to use history.pushstate, all effects are performed in one page. After changing the page content with js, you can use pushstate to change the url, which makes it like navigating with effects.
To read more about pushstate, please refer https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history

Categories