I created an animation with TweenMax, that animate a div from 100% width of it's parent to zero. I have three divs next to each other, that are overlapping the image below. Now I would like that each preload div class will start some seconds after the previous one was triggered.
I try something like setTimeout, but I couldn't get it work.
How can I achieve above?
CodePen: https://codepen.io/anon/pen/aWVZXL
I have changed the script. Please refactor if you want.
$(document).ready(function() {
var toBeAnimated;
var currentAnimat = 0;
$('.link').click(function() {
toBeAnimated = $(".preloader");
console.log('lets start animation');
preload(toBeAnimated[currentAnimat]);
});
function preload(elem) {
var elem = $(elem);
var width = elem.outerWidth();
// Tween out preload div
TweenMax.to(elem, 1.4, {
width: 0,
right: 0,
onComplete: function() {
elem.remove();
currentAnimat++;
if(currentAnimat >= toBeAnimated.length) {
console.log('Animation done');
} else {
preload(toBeAnimated[currentAnimat]);
}
}
});
}
});
Related
I have a class of .header-is-active that is applied to the <body> tag when a user scrolls.
I would like an animation to be triggered when the class is added and then the animation to run in reverse when the class is removed.
Everything happens as expected except for the animation. I'm using jQuery and Greensock to make everything happen.
Here's what I currently have:
$(function() {
var body = $('body');
var trigger = $('.trigger');
var tween = TweenMax.to(trigger, 0.5, {css:{height: "100vh"},});
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
body.addClass('header-is-active');
tween();
} else {
body.removeClass('header-is-active');
}
});
});
The issue I have is the tweened value height: 100vh is being applied regardless with .header-is-active or not. Is there something missing?
At the end of your $(window).scroll() function, give this a shot:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
body.addClass('header-is-active');
tween();
} else {
body.removeClass('header-is-active');
}
// jQuery way
if(body.hasClass('header-is-active')) {
// Run animation
} else {
// Run reverse animation
}
// Non-jQuery way (just for reference)
var body = document.body;
if(body.classList.contains('header-is-active') {
// Run animation
} else {
// Run reverse animation
}
});
If it doesn't work, since it's running async, you can add a setTimeout() to the above so it's called after your function. It should look something like this
setTimeout(function() {
if(body.hasClass('header-is-active')) {
// run animation
} else {
// run reverse
}
}, 0);
Here is a code that should open and close my site's menu. The menu is divided to divs and each one is timed to enter the screen after the other.
<script type="text/javascript">
var s=0;
function menuOpen() {
if (s==0){
document.getElementById("menu_icon").src = "x.png";
document.getElementById("nav_menu").style.zIndex = "3";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.remove('loading');
}, index * 100);
});
s++;
} else {
document.getElementById("menu_icon").src = "menu_icon.png";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.add('loading');
}, index * 100);
});
s=0;
// how to make this part run after the menu has finished folding?
setTimeout(function(){
document.getElementById("nav_menu").style.zIndex = "1";
}, 1500);
}
}
</script>
The content of the page is at z-index 2. The menu when folded is at 1 and when open at 3.
Is there a way to run the command moving the menu to z-index 1 after the menu has finished folding completely?
Currently what I did was to time the animation (1600ms) and use setTimeout. But this timing will change if I'll add more lines to my menu or if someone is clicking rapidly on the menu icon.
I'm rather new to JS and Jquery so go easy on me (:
Thanks of your help.
Below you can find the code and link to jsfiddle. Unfortunetly jsfiddle blocks the animate method for unknown reason so I don't debug, but even if it code will not work :))) I hope you will cathch the idea. And also some explanation.
Firstly our items are hidden. There are two functions displayMenu and hideMenu, they are similar, but display - run animations from the top invisible, and hide - start hide items from the bottom visible. To prevent mess I use two flags and two classes, first openFlag it is say what animations should be played now. Our hide and display functions are recursive and after they end current animation(hide or show) they check openFlag, and play next hide/show or start another chain of hide/show functions. It is the most difficult to understand part) But important that with it you can click as many times as you want and all would be fine and would be never broken by clicks.
Two classes we use as animation-chain can change behaviour and we need the way to choose items that alredy visible or hidden, so this why after each animation we set only one of this classes and remove another.
Now there is one problem if all animation are ended when we click button we should start new chain of animations, but if chain has been already started we need just to switch openFlag, and when current animation stops, it will change the behaviour. So this is the reason for btnFlag it is 1 if no active chain-animations at this moment.
After the last execution of element of animation-chain it will call callback arg, that you should pass, also at this moment will set btnFlag to 0, that means that animation-chain stopped. The openFlag as you remember changed at moment og click.
function end() {
console.log("here you can set zIndex");
}
var openFlag = 0; //become 1 after we start open elems
var btnFlag = 1;
$(document).ready(function() {
$('.toggleMenu').click(function() {
if (!$('.menuBlocks').hasClass('visible')) {
if (openFlag == 0) {
openFlag = 1;
if (btnFlag) {
var items = $('.invisibleItem');
var amount = items.length;
displayMenu(0, amount, items, end);
}
}
} else {
openFlag = 0;
if (btnFlag) {
var items = $('.visibleItem');
var amount = items.length;
hideMenu(amount - 1, items, end);
}
}
});
});
function displayMenu(i, amount, items, callback) {
if (i < amount && openFlag) {
items[i].animate({
"width": "100px"
}, 1000, function() {
items[i].removeClass('invisibleItem');
items[i].addClass('visibleItem');
displayMenu(i + 1, amount, items);
});
} else if (!openFlag) {
var items = $('.visibleItem');
var amount = items.length;
hideMenu(amount - 1, items, makeToggleVisible);
} else {
btnFlag = 1; //all aniimations ended
callback();
}
}
function hideMenu(i, items, callback) {
if (i < 0 && openFlag) {
items[i].animate({
"width": "0px"
}, 1000, function() {
items[i].removeClass('visibleItem');
items[i].addClass('invisibleItem');
hideMenu(i - 1, amount, items);
});
} else if (!openFlag) {
var items = $('.invisibleItem');
var amount = items.length;
displayMenu(0, amount, items, makeToggleVisible);
} else {
btnFlag = 1; //all animations are ended
callback();
}
}
https://jsfiddle.net/ShinShil/nrtyshv5/4/
Ok fixed it.
I moved everything to jquery. Used animate and promise.
This is what came out at the end. It is a side menu that will open it's li elements one-by-one.
var s=0;
var navMenu = document.getElementById("nav_menu");
var navBtn = document.getElementById("btn");
$(document).ready(function(){
$("button").click(function(){
if (s==0) {
navMenu.style.zIndex = "4";
navBtn.classList.add('close');
$('ul').each(function() {
$(this).children().each(function(i) {
$(this).delay(i * 100).animate({left:0});
});
});
$( "li" ).promise().done(function() {
navMenu.style.zIndex = "4";
});
s++;
}
else {
navBtn.classList.remove('close');
$('ul').each(function() {
$(this).children().each(function(i) {
$(this).delay(i * 100).animate({left:"100%"});
});
});
s=0;
$( "li" ).promise().done(function() {
navMenu.style.zIndex = "1";
});
}
});
});
and with CSS transitions.
var s=0;
function menuOpen() {
if (s==0){
document.getElementById("menu_icon").src = "x.png";
document.getElementById("nav_menu").style.zIndex = "3";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.remove('loading');
}, index * 100);
});
s++;
$("#last").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
document.getElementById("nav_menu").style.zIndex = "3";
});
} else {
document.getElementById("menu_icon").src = "menu_icon.png";
$('.box-wrapper').each(function(index, element) {
setTimeout(function(){
element.classList.add('loading');
}, index * 100);
});
s=0;
$("#last").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
document.getElementById("nav_menu").style.zIndex = "1";
$("#nav_menu").scrollTop(0);
});
}
}
so i've made a jquery carousel which you can see here: http://teste.boleiafacil.com/ (it's the one in the end of the page
this is the jquery:
//highlights slide animation
var prdlength = $(".rproducts").length;
var prdleft = 1;
var i = 0;
function swapC() {
i++;
prdleft++;
$(".rproducts").each(function(){
$(this).animate({"left":"-" + prdleft + "px"}, 10);
if (prdleft == 180){
$(this).appendTo(".rproductswrapper");
prdleft = 0;
}
});
if (i == prdlength) {
i = 0
}
window.setTimeout(function() { swapC() }, 10);
}
$(window).on("load", swapC);
the problem is when the divs get appended to the end of the wrapper it looks glitchy.
how can i fix this?
Try wrapping your function in a document ready rather than window load, the shorthand for it is:
$(function(){
//code here
});
Creating an accordion - on the slide - the elements underneath the element that is sliding seem to move down a px and then back up, creating a juddering effect.
$(document).ready(function() {
//Promos banners rotation and accordion
$(function(){
var $accordionList = $('.accordion').find('li');
var numberOfItems = $accordionList.length;
var currentItem = 0;
// Set first item to active
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {});
// Loops through promos
var infiniateLoop = setInterval(function() {
if(currentItem == numberOfItems - 1){
currentItem = 0;
}
else {
currentItem++;
}
// Remove active class, if is has it, and close content
$accordionList.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {
});
}, 4000 );
// Click to show promo
$accordionList.on('click', function () {
// Stop rotation
clearInterval(infiniateLoop);
var $accordionHead = $(this);
// Remove active class, if is has it, and close content
if($accordionHead.hasClass('active')) {
// Do nothing
}
else {
$accordionHead.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionHead.addClass('active').find('.content').slideToggle(800, function() {
});
};
});
});
});
Fiddle here demonstrating the problem
I've seen some suggestions that you fix the height of the content div - but the site is responsive so that won't work.
Ya, I've had this problem before to. My favorite fix is to just make my own .slideToggle()
div = $('div');
height = div.height();
width = div.width();
$('div').click( function() {
if ($(this).hasClass('hidden')) {
$(this).animate({height: "0", width: "0"}, 200).hide().addClass('hidden');
} else {
$(this).animate({height: height, width: width}, 200).show().removeClass('hidden');
}
});
You could even wrap it in a prototype function if you wanted to.
Currently I am developing a simple show/hide div function with JavaScript. Now I have made it partially work. Take a look or you can copy and paste and try my code on your com. Here is the code:
http://jsfiddle.net/HRn3Q/
The current problem is I don't know how to trigger the content in the drop down list and show/hide it at the same position as graph1, graph2 and graph3 etc...I also want something like when diagram 1 is being shown then when I click show div 2, the content of diagram 1 will be replaced by graph2. I hope I have state my question clear.
This should do it.
The page wasn't recognizing the functions in that state for some reason.
turned:
function toggleStock(id)
{
}
into:
toggleStock = function(id)
{
}
http://jsfiddle.net/HRn3Q/
<script>
var opacity =0;
var intervalId =0;
function fadein()
{
intervalId = setInterval(hide,200)
}
function hide()
{
var img = document.getElementById("img1");
opacity = Number(window.getComputedStyle(img).getPropertyValue("opacity"));
if(opacity>0)
{
opacity=opacity-0.2;
img.style.opacity=opacity;
}
else
{
clearInterval(intervalId);
}
}
function fadeout()
{
intervalId = setInterval(show,200)
}
function show()
{
var img = document.getElementById("img1");
opacity = Number(window.getComputedStyle(img).getPropertyValue("opacity"));
if(opacity<1)
{
opacity=opacity+0.1;
img.style.opacity= opacity;
}
else
{
clearInterval(intervalId);
}
}
</script>