I have a simple wrapper div that I animate in using velocity.js UI pack. In the complete callback function, I am using a combination of UI pack and blast.js to animate three sentences.
The problem is that my sentences are initially shown, and only after that they are animated. They shouldn't be visible after the wrapper div is animated into view.
Everything is working fine if I don't animate the wrapper div, guess the opacity settings during animation are messing with child elements.
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$(".animated")
.blast({ delimiter: "character" })
.velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60,
delay: 400
});
}
})
Here is the fiddle to see the problem : http://jsfiddle.net/vcsr6aqj/1/
The problem is that your p tags aren't at opacity: 0, but only their characters, which are inside a span having as class blast. Since your invisible characters are only created when you call $(".animated").blast({ delimiter: "character" }), which means once your wrapper has completed its apparition, the sentences will be visible until then. So you have two possibilities that I can think of.
Create your span characters with blast at the page load, instead at the wrapper velocity complete and then call velocity on your created spans:
$(document).ready(function() {
$(".animated").blast({ delimiter: "character" });
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$(".animated .blast").velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60,
delay: 400
});
}
})
});
JSFiddle example
Add a class to your p tags having opacity: 0:
<p class="animated no-opacity">Sentence number one.</p>
<p class="animated no-opacity">Sentence number two.</p>
<p class="animated no-opacity">Just one sentence more.</p>
CSS:
.no-opacity {
opacity: 0;
}
When your wrapper has completed the velocity, remove the class from your p tags. Also, remove delay: 400 from your velocity attributes, otherwise the sentences will show for 400 milliseconds:
$(document).ready(function() {
$('.wrap').velocity('transition.slideUpIn', {
delay: 1000,
display: null,
complete : function(){
$animated = $(".animated");
$animated.removeClass("no-opacity");
$animated.blast({ delimiter: "character" })
.velocity("transition.fadeIn", {
display: null,
duration: 1000,
stagger: 60
});
}
})
});
JSFiddle example
Here you go (fiddle). I'm sure there are more elegant solutions.
It appears that the slideUpIn animates opacity from 0 to 1, including the opacity of .animated which is probably 'inherited'. Setting it to 0 to hide it fixes it, but then .blast() doesn't work, so we enable it again.
Related
I have elements on a page that I want to animate in to view, but after they've animated in, I want to defer further animation on them to CSS (by changing classes)... I am finding that Velocity leaves all my animated properties in the style= tag and makes CSS transitions impossible.
I have a solution below, but resetting the CSS on complete seems iffy, I was wondering if there's a better way to do it?
// first use CSS to hide the element and squish it
$el.css({
width: 0,
left: "-10px",
opacity: 0,
marginRight: 0,
transition: "none"
})
// now animate the width and margin (do this first
// so there's a little gap between existing elements
// before we fade in new element.
.velocity({
width: width,
marginRight: margin
}, {
queue: false,
duration: 230
})
// then fade and move in the new element,
// but this is the iffy bit when it completes
// I have to unset all the styles I've animated?
.velocity({
left: 0,
opacity: 1
}, {
queue: false,
duration: 100,
delay: 130,
complete: function(els) {
$(els).css({
width: "",
left: "",
opacity: "",
marginRight: "",
transition: ""
});
}
});
Typically, you want animation engines to leave styles inline; otherwise final values will pop as they get overwritten by stylesheets upon removal.
You can also do $(els).attr("style", ""); to just clear all styles.
I'm working on a project with a push menu. When the content div slides over, the menu buttons have a little animation as they enter the screen. It doesn't take long or anything but the issue I'm having is if the user opens and closes the menu quickly a bunch of times in a row, the items on the list begin disappearing and reappearing in the wrong order. I think this is because the new animation calls are canceling out old ones and in general screwing up the order of things.
Ideally, I'd like the animations to always behave properly (i.e. if the menu is opening, clear all previous animations and play the opening animation only).
But I'd be satisfied if I could at least get each element to queue its animations properly so that the elements in the menu don't randomly disappear upon opening the menu.
Here is a fiddle of the problem:
http://jsfiddle.net/9t10zr6m/1/
The top div is transparent because it normally has a background image. And also because I thought it might be easier to see the problem with the menu if you could see what was going on underneath the top div.
here is the relevant jQuery code:
$(document).ready(function() {
$(".expandable-content").on('click', function(){
$(this).children(".internal-content").slideToggle();
});
$(".menu-button").on('click', function(){
var position = $(".blue-box").css("left");
if( position == "0px") {
$(".blue-box").velocity({left: "250px"}, 500);
$('.side-nav-link').finish();
$('.side-nav-link').velocity('transition.slideUpIn', { stagger: 50 });
} else {
$(".blue-box").velocity({left: "0px"}, 500);
$('.side-nav-link').finish();
$('.side-nav-link').velocity('transition.slideDownOut', { stagger: 50 });
}
});
});
and the relevant html:
<div class="blue-box">
<h1>Julian Ptak</h1>
<h2>Kempis Coder. Simplicity. Purity.</h2>
<div class="menu-button"><img class="button-icon" src="img/menu-icon.png"><p class="button-text">Menu</p></div>
</div>
<div class="red-box">
<ul class="side-nav">
<li class="side-nav-link">Home</li>
<li class="side-nav-link">Work</li>
<li class="side-nav-link">Hobbies</li>
<li class="side-nav-link">Writings</li>
<li class="side-nav-link">Code</li>
<li class="side-nav-link">Contact</li>
</ul>
</div>
How do you make jQuery enqueue animations? Or only play the right animation for the right click and skipping all previous ones?
I tried .finish() and .stop() but neither seemed to fix my problem. Any ideas? Do those not work with velocity.js?
Very long question!!
I don't get what you want, but according to some keywords in your question i will give you some Velocity features:
Velocity add animations to its queue by default!
$elm.velocity({ /* 1 */ },{});
$elm.velocity({ /* 2 */ },{});
in this example at the end of first animation second animation will start.
$elm.velocity({ /* 1 */ },{});
$elm.velocity({ /* 2 */ },{queue: false});
in this example both animations start together.
$elm.velocity('stop', true).velocity({ /* 1 */ },{});
in this example velocity('stop', true) clear the $elm queue then next animation immediately start.
Be careful to use the delay param for velocity
for example :
jQuery(function($){
var $pen = jQuery('#pen');
$arrow1 = jQuery('#arrow1');
$arrow2 = jQuery('#arrow2');
$pdf = jQuery('#pdf');
$screen = jQuery('#screen');
$pen
.velocity("fadeIn", {
duration: 1500,
complete:function(elements){
$arrow1.velocity("fadeIn", { duration: 1500});
}
});
});
The callback start after the end of the animation
in the meantime
$pen.velocity("fadeIn", { duration: 1500 });
$arrow1.velocity("fadeIn", { duration: 1500});
});
the two animations start at the same time, so if you want a timeline, write a delay for start after the end of the first animation
$pen.velocity("fadeIn", {
duration: 1500
});
$arrow1.velocity("fadeIn", { duration: 1500,delay:1500});
});
Nevermind with the ui Pack you've a great explanation here
Ui pack sequence
But for make the same thing, you can't use "fadeIn" directly
here we go
var $pen = jQuery('#pen');
$arrow1 = jQuery('#arrow1');
$psd = jQuery('#psd');
$arrow2 = jQuery('#arrow2');
$screen = jQuery('#screen');
var sequenceFade = [
{ e: $pen, p: { opacity: 1 , display: "block"}, o:{duration :1500}},
{ e: $arrow1, p: { opacity: 1 , display: "block"}, o: {duration: 1500}},
{ e: $psd, p: { opacity: 1 , display: "block"}, o: {duration: 1500}},
{ e: $arrow2, p: { opacity: 1 , display: "block"}, o: {duration: 1500}},
{ e: $screen, p: { opacity: 1 , display: "block"}, o: {duration: 1500}}
];
$.Velocity.RunSequence(sequenceFade);
How would one make a slide and fade in animation like in seen in the green and pink boxes on sharethis.com? In particular I like the one in the blue box with the arrows. Are there a set of JavaScript codes or CSS effects?
The easiest would probably be to use a library like this:
http://janpaepke.github.io/ScrollMagic/
I see that for the arrows effect the css-height property is animated when you scroll. This is done in javascript. But you can also achieve this effect through CSS3-transitions.
Update: Slide and wipe effects from the demo page:
// ani
var pinani = new TimelineMax()
// wipe
.add(TweenMax.to("#wipe", 1, {
width: "100%"
}))
// slide
.add(TweenMax.to("#slide", 1, {
top: "0%",
ease: Bounce.easeOut,
delay: 0.2
}));
// pin
new ScrollScene({
triggerElement: "section#pin",
duration: 1100
})
.on("progress", function () {
// keep centered even though width changes
$("#wipe h3").width($("#pin>h3").width());
})
.setTween(pinani)
.setPin("section#pin")
.addTo(controller);
I'm using carouFredSel to create a vertical carousel. Everything works great, except I would prefer if partial items would be shown at the bottom, cropped, rather than being hidden. This way it would indicate to users that there are additional items that can be scrolled.
I have been reading the documentation, but so far can't tell if what I am after is possible.
Check out the JSFiddle to see what I mean. Watch the bottom most item on the page.
Javascript
$("ul").carouFredSel({
direction: "up",
align: "top",
width: 100,
height: "100%",
items: {
visible: "variable",
width: 100,
height: "variable"
},
scroll: {
items: 1,
mousewheel: true,
easing: "swing",
duration: 500
},
auto: false,
prev: {
button: ".prev",
key: "up"
},
next: {
button: ".next",
key: "down"
}
});
This is a bit of a hack, but it works. Set the height of the scroller (in this case, ul) to 150% and the parent element (in this case, body) to overflow: hidden. Now the bottom most element is off screen.
Javascript
$("ul").carouFredSel({
height: "150%"
});
CSS
body {
overflow: hidden;
}
Ha, caroufredsel supports it, no hacks required :))! You can achieve it with the following option:
items: {
visible: '+1'
}
EDIT: This suffers from a problem though. If number of whole visible items + 1 == number of all items, then carousel cannot be scrolled even though one image is visible just partially. You can overcome this issue by setting e.g. minimum: 1 but it is not always a way to go (e.g. if number of images is dynamic and you don't want scroll handlers to appear when there is just one or two images.).
The next not visible element in the vertical carousel is pushed down by the margin.
I'm currently overriding it by the following function:
function cropCarousel () {
var visibleElements = this.triggerHandler("currentVisible"), // show all visible
$lastElement = $(visibleElements[visibleElements.length - 1]); // get the last one
$lastElement.css('margin-bottom', '30px'); // amend the margin
};
cropCarousel.call($('#your_carousel_id'));
The downside of it that you will have to call this function on carousel init and on up and down events. But it works ;)
I have found jQuery: FadeOut then SlideUp and it's good, but it's not the one.
How can I fadeOut() and slideUp() at the same time? I tried two separate setTimeout() calls with the same delay but the slideUp() happened as soon as the page loaded.
Has anyone done this?
You can do something like this, this is a full toggle version:
$("#mySelector").animate({ height: 'toggle', opacity: 'toggle' }, 'slow');
For strictly a fadeout:
$("#mySelector").animate({ height: 0, opacity: 0 }, 'slow');
Directly animating height results in a jerky motion on some web pages. However, combining a CSS transition with jQuery's slideUp() makes for a smooth disappearing act.
const slideFade = (elem) => {
const fade = { opacity: 0, transition: 'opacity 400ms' };
elem.css(fade).slideUp();
};
slideFade($('#mySelector'));
Fiddle with the code:
https://jsfiddle.net/00Lodcqf/435
In some situations, a very quick 100 millisecond pause to allow more fading creates a slightly smoother experience:
elem.css(fade).delay(100).slideUp();
This is the solution I used in the dna.js project where you can view the code (github.com/dnajs/dna.js) for the dna.ui.slideFade() function to see additional support for toggling and callbacks.
The accepted answer by "Nick Craver" is definitely the way to go. The only thing I'd add is that his answer doesn't actually "hide" it, meaning the DOM still sees it as a viable element to display.
This can be a problem if you have margin's or padding's on the 'slid' element... they will still show. So I just added a callback to the animate() function to actually hide it after animation is complete:
$("#mySelector").animate({
height: 0,
opacity: 0,
margin: 0,
padding: 0
}, 'slow', function(){
$(this).hide();
});
It's possible to do this with the slideUp and fadeOut methods themselves like so:
$('#mydiv').slideUp(300, function(){
console.log('Done!');
}).fadeOut({
duration: 300,
queue: false
});
I had a similar problem and fixed it like this.
$('#mydiv').animate({
height: 0,
}, {
duration: 1000,
complete: function(){$('#mydiv').css('display', 'none');}
});
$('#mydiv').animate({
opacity: 0,
}, {
duration: 1000,
queue: false
});
the queue property tells it whether to queue the animation or just play it right away
Throwing one more refinement in there based on #CodeKoalas. It accounts for vertical margin and padding but not horizontal.
$('.selector').animate({
opacity: 0,
height: 0,
marginTop: 0,
marginBottom: 0,
paddingTop: 0,
paddingBottom: 0
}, 'slow', function() {
$(this).hide();
});