fadeTo breaks smooth scroll - javascript

I'm using this snippet I found online to smooth scroll:
$( "a[href*='#']" ).on( "click", function( event ) {
event.preventDefault();
var href = event.target.href;
href = href.slice( href.indexOf( "#" ), href.length );
$( "body" ).animate( {
scrollTop: $( href ).get( 0 ).offsetTop
}, 1000 );
} );
It works just fine but it breaks when it comes across an image that is fading in. I have some images set to fadeTo from opacity 0 to 1 and when the scroll animation comes across those images it stops dead in it's tracks. In other words, the smooth scroll always stops at my first div because there are images fading in that stop the scroll so the scroll animation never takes the user to their desired destination.
How can I remedy this?

The janky-ness you're seeing is due to the extra rendering required to update the opacity of the images during the scroll, versus the scroll alone.
I'd suggest your best bet would be to disable the fade whilst the scroll is occurring.
To do this you could either set opacity to 1 for all images before calling animate(), or to prevent the fade from occurring until after the animation is complete, however the method to do this would depend on the code/framework used for the image fade.

Related

How to make a transform animation

I have a script for my HTML page. I want to make the following in that script:
Show a preloading #id for some seconds and then fade out;
While the div is loading the main page under that div which is shown cause my opacity is to 0.7 I want to tranform the nav-bar up to browser windows so bassically hide it and in that position to tranform a new nav-bar.
I want that to take place while the preloading page is working not after!
And I want to show more contects in parraler with the nav-bar animation.
I created the script but I get lost in how to position my actions and I don't know if I made anything corrdctly. I make the fade out preloader.
$(window).load(function(){
$("#fade").css({opacity: 0.7})
$("#fade").delay(4000).fadeOut(1000, function() {
$('#nav-before').transition({ y: '40px' }); //now I want to hide the nav
//and show the new with id="nav-after"
//and in parraller with the above to be able to load more contects
$("#fade").remove(); //when evrything finished kill the div
});
});
$( "#fade" ).animate({
opacity: 0.0
}, 5000, function() {
// Animation complete.
});
You can play with animate. Here is the reference: jquery.com/animate/

Using .offset().top with .slideUp

I'm trying to make the window scroll to an element on click. It is working, except when the slideUp animation of one of the previous elements fires, the clicked element scrolls up way past the top.
Here's the link: http://jtwebfolio.com/mobi
NOTE: Size your browser down to mobile width to best see the issue. Also, this is taking place on the portfolio projects.
Here's the code:
$('article.project header').click(function(){
if($(this).parent().hasClass('clicked')){
// If the clicked project has already been clicked, remove the class and hide the content
$(this).parent().removeClass('clicked');
$(this).parent().find('.proj_content').slideUp('fast');
}else{
// Remove the class and slide the content up on all projects
$('article.project').removeClass('clicked');
$('article.project .proj_content').slideUp('fast');
// Add the class and show the content on the selected project
$(this).parent().addClass('clicked');
$(this).parent().find('.proj_content').slideDown('fast');
// Slide the project to the top after clicking on it
$('html, body').delay(500).animate({
scrollTop: $(this).parent().offset().top
}, 500);
}
});
If someone could help me produce the desired effect, that would be amazing. Thanks in advance!
A couple of things:
Your .slideDown()s use the speed fast, but you're only delaying by 500ms. fast is synonymous with 600ms. In general, I think it's a bad idea to use both as it's very confusing to someone reading your code what fast is.
Rather than using .delay() method, I'd use the complete argument on the slideDown or slideUps, so that once they're complete, you do your scrolling. This makes more sense, as you'd then not have to worry about conflicting timings.
My guess would be that your problem is caused by your transitions taking 600ms, but your scroll only waiting 500ms. At 500ms, it's getting the wrong offset values and scrolling to those.
Perhaps you should consider changing your markup to something like:
$(this).parent().find('.proj_content').slideDown('600', function() {
// Slide the project to the top after clicking on it
$('html, body').animate({
scrollTop: $(this).parent().offset().top
}, 500);
});
* Note: I've changed fast to 600 for clarity's sake.
try this :
$('article.project').on('click','header',function(){
_parent = $(this).parent();
if(_parent.hasClass('clicked')){
// If the clicked project has already been clicked, remove the class and hide the content
_parent.removeClass('clicked');
.find('.proj_content')
.slideUp('fast');
}else{
// Remove the class and slide the content up on all projects
$('article.project').removeClass('clicked')
.children('.proj_content')
.slideUp('fast');
// Add the class and show the content on the selected project
// Slide the project to the top after clicking on it
_parent.addClass('clicked')
.find('.proj_content')
.slideDown('fast',function(){
// callback
$('html, body').animate({ scrollTop: +(_parent.offset().top)+'px' }, 500);
});
}
});

How do I stop a bouncy JQuery animation?

In a webapp I'm working on, I want to create some slider divs that will move up and down with mouseover & mouseout (respectively.) I currently have it implemented with JQuery's hover() function, by using animate() and reducing/increasing it's top css value as needed. This works fairly well, actually.
The problem is that it tends to get stuck. If you move the mouse over it (especially near the bottom), and quickly remove it, it will slide up & down continuously and won't stop until it's completed 3-5 cycles. To me, it seems that the issue might have to do with one animation starting before another is done (e.g. the two are trying to run, so they slide back and forth.)
Okay, now for the code. Here's the basic JQuery that I'm using:
$('.slider').hover(
/* mouseover */
function(){
$(this).animate({
top : '-=120'
}, 300);
},
/* mouseout*/
function(){
$(this).animate({
top : '+=120'
}, 300);
}
);
I've also recreated the behavior in a JSFiddle.
Any ideas on what's going on? :)
==EDIT== UPDATED JSFiddle
It isn't perfect, but adding .stop(true,true) will prevent most of what you are seeing.
http://jsfiddle.net/W5EsJ/18/
If you hover from bottom up quickly, it will still flicker because you are moving your mouse out of the div causing the mouseout event to fire, animating the div back down.
You can lessen the flicker by reducing the delay, however it will still be present until the delay is 0 (no animation)
Update
I thought about it and realized that there is an obvious solution to this. Hoverintent-like functionality!
http://jsfiddle.net/W5EsJ/20/
$(document).ready(function() {
var timer;
$('.slider').hover(
/* mouseover */
function(){
var self = this;
timer = setTimeout(function(){
$(self).stop(true,true).animate({
top : '-=120'
}, 300).addClass('visible');
},150)
},
/* mouseout*/
function(){
clearTimeout(timer);
$(this).filter(".visible").stop(true,true).animate({
top : '+=120'
}, 300).removeClass("visible");
}
);
});
You could use .stop() and also use the outer container position
$(document).ready(function() {
$('.slider').hover(
/* mouseover */
function(){
$(this).stop().animate({
top : $('.outer').position().top
}, 300);
},
/* mouseout*/
function(){
$(this).stop().animate({
top : $('.outer').position().top + 120
}, 300);
}
);
});
​
DEMO
Hope this helps
Couldn't reproduce your issue but I believe that hover is getting called multiple times. To work around this you can check if the div is already in animation. If yes, then don't run another animation again.
Add following piece of code to check if the div is already 'animating':
if ($(this).is(':animated')) {
return;
}
Code: http://jsfiddle.net/W5EsJ/2/
Reference:http://api.jquery.com/animated-selector/
I understand the problem and reproduced it, it happens when hovering from the bottom up. The hovering with the mouse is what's causing the problem since the animation function will be called when the mouse hovers over the image. You need to control what happens here by using mouse enter and mouse leave, check out a similar example: Jquery Animate on Hover
The reason it's like that is because the hover is getting queued up causing it to slide up and down multiple times. There's a plug-in called hoverIntent which fixes the issue. http://cherne.net/brian/resources/jquery.hoverIntent.html
If you do decide to use hoverIntent, the only thing you have to change in your code is .hover > .hoverIntent

Animating active (hovered) thumbnail opacity in a gallery with jquery

I'm trying to animate the opacity. Default opacity is 0.8 for all thumbnails. Once hovered, the opacity increases to 1 and should go back to 0.8 when another thumbnail is hovered.
I've tried this code:
container.delegate("a:has(img)", "mouseenter", function(e){
$(e.currentTarget).stop(true, true).animate({opacity: 1}, options.thumbsopacityFadeTime);
}).delegate("a:has(img)", "mouseout", function(e){
$(e.currentTarget).stop(false, true).animate({opacity: options.thumbsOpacity}, options.thumbsopacityFadeTime);
);
but the hovered thumbnails sometimes (most of the time) goes back to the default opacity, even when the mouse is still over that same thumbnail and hasn't moved.
I assume this has something to do with the animations currently running and what not, but I thought $(e.currentTarget) would only apply to this 1 thumbnail, so why would a mouse out event be triggered for that thumbnail when I do not leave the thumbnail?
Any ideas on how to fix this?
Thanks,
Wesley
Did I understand you that you don't want to have mouseout effect? Only when hovering different thumbnail?
FIrst attempt should be replacing "mouseout" to "mouseleave". If it doesn't help, try different way:
var obj = container.find("a:has(img)");
obj.bind({
mouseenter:function(){
obj.stop().not(this).animate({opacity: options.thumbsopacity}, options.thumbsopacityFadeTime);
$(this).animate({opacity: 1}, options.thumbsopacityFadeTime);
},
mouseleave:function(){
// nothing :)
}
});

jQuery's stop() seems to be blocking animations that haven't been queued yet

How does jQuery's stop() actually work?
If you look here (http://jsfiddle.net/hWTT6/), when you hover over the main blue box it should fade to red, and when you hover off it should fade back. The problem is it will completely fade to red (and then back to blue) even if the mouse has hovered off before the first fade was complete. The problem can more clearly be seen with the slide effect. Hover over the slide "button" and the main box will slide to blue, hover off, it will slide back. But try hovering on and off and on and off, before the first animation has completed. You'll see that all four animations are carried out. I included both examples here to show it is not just a problem with one effect or something.
I thought this would be easily fixed by adding a stop before the animations, as shown commented out in the code. But, if I do this the current animation will stop and the following one will never start. Almost as though stop is blocking an animation that is occurring after the call to stop.
What am I missing here?
Thanks.
You are missing that .stop() accepts two arguments. Both boolean, indicating:
- clearQueue (first)
- jumpToEnd (second)
So by calling $('#foo').stop( true, true ).doSomeOtherStuff() you should get your desired goal.
Reference: .stop()
The problem is the CSS is getting messed up by stopping at arbitrary points.
The fadeIn(), fadeOut(), slideUp() and slideDown() move from the current state to a new one and then revert to that - not to the original CSS.
You need to fix the CSS back in to a usable state to continue with after the .stop(), or more clearly specify the animation targets.
As the others have said, you can get the CSS to the correct position, by ensuring that when you stop the animation, it jumps to the end of it, rather than leaving everything in an arbitrary state.
UPDATE:
Take a look at the code in this update of your demonstration: http://jsfiddle.net/hWTT6/5/
It might not be exactly how you want it to perform, but the trick, if you do not want the animation to run its course, is to get the animation back in to a state that it can continue from in the way in which you desire.
$(function() {
$('#fade')
.mouseenter(function() {
$('#fg_fade').stop().animate({ 'opacity': 0 }, 'slow', function() {
$('#fg_fade').css('height', '100%');
});
})
.mouseleave(function() {
$('#fg_fade').stop().animate({ 'opacity': 1, 'height': '100%' }, 'slow');
});
$('#slide_fire')
.mouseenter(function() {
$('#fg_fade').stop().animate({ 'height': 0 }, 'slow', function() {
$('#fg_fade').css('opacity', 1);
});
})
.mouseleave(function() {
$('#fg_fade').stop().animate({ 'height': '100%' }, 'slow', function() {
$('#fg_fade').css('opacity', 1);
});
});
});
You could set the stop() options to (true, true) so that you cancel all events in cue and jump to the end of the previous animation. look at the fiddle:http://jsfiddle.net/hWTT6/4/
The stop method can be called in the following difference ways:
.stop(true);
//Same as:
.stop(true, false); //Empty the animation queue only
//Or
.stop(true,true); // Empties the animation queue AND jumps to the end
//Default
.stop()
//Same as
.stop(false,false);
There may be a better way using .animate instead: Demo Here
$(function() {
$('#fade')
.mouseenter(function() {
$('#fg_fade').stop().css('height', '10em').animate({'opacity' : '0'}, 'slow');
})
.mouseleave(function() {
$('#fg_fade').stop().css('height', '10em').animate({'opacity' : '1'}, 'slow');
});
$('#slide_fire')
.mouseenter(function() {
$('#fg_fade').stop().css('opacity', '1').animate({'height' : '0'}, 'slow');
})
.mouseleave(function() {
$('#fg_fade').stop().css('opacity', '1').animate({'height' : '10em'}, 'slow');
});
});
This way the animation stops when you want it to and still runs the next animation.
The problem with doing .stop then slideUp/slideDown or fadeIn/fadeOut is that the animation can end prematurely and keep an incorrect height/opacity.
The problem is caused by the way fadeIn, fadeOut etc. work. You may expect them to fade between 0 and 1. However, in reality they fade between 0 and whatever the "baseline" opacity is. You can see this here:
http://jsfiddle.net/hWTT6/7/
You'll notice I set the initial opacity to .5. Now when I call fadeIn it does not fade all the way in to 1 it fades to my baseline of .5. Your problem occurs when you stop the animation prematurely, the "baseline" becomes whatever the opacity is at the time it is stopped. Now when you call fadeIn on mouseleave it tries to fade to this new baseline and finds it is already there. You can see this illustrated by going here:
http://jsfiddle.net/hWTT6/8/ (original, but with .stop)
If you place your mouse over slide and then remove it half-way through the animation, it will stop in the middle. Now place your mouse back over slide and wait for the animation to complete. If you now remove your mouse, you will see that it slides back down to the place where the first animation was stopped. That is because this is the new "baseline".
The way that you would solve this is actually to replace fadeIn, fadeOut, etc. with a more explicit animation. For instance, use fadeTo to tell it to fade between 0 and 1:
http://jsfiddle.net/hWTT6/6/
Notice that since I am telling it to fade to 0 or 1 everything works. A similar thing could be done to replace slideUp and slideDown using animate.

Categories

Resources