I try to use jQuery visible plugin to detect if an element is or isn't visible in the viewport. I use a code like this:
animateFrontPage: function(){
var apps = 0;
if($('#apps-shelf').visible(true)) {
apps = 1;
if(apps == 1) {
$('#apps-shelf li').velocity("transition.bounceUpIn", { stagger: 150 });
apps = 0
}
}
}
and I run it with scroll function:
$(window).scroll(function() {
Functions.animateFrontPage();
});
The problem is - animation repeats itself with every scroll. What can I do to prevent it?
If you only want the animation to show once, what you could do is add a class to the element to flag that it is finished - then each time you only carry out the animation if the element does not have this class. Perhaps something along these lines :
animateFrontPage: function(){
var $el = $('#apps-shelf');
if($el.visible(true) && !$el.hasClass('finished')) {
$el.addClass('finished');
$el.find('li').velocity("transition.bounceUpIn", { stagger: 150 });
}
}
Update
This is the else statement you need if you want the other animation to run on these conditions : a) the animation of the first element $('#apps-shelf') has already happened and b) the element $('#apps-shelf') is no longer visible on the screen (you have scrolled past it for example)
animateFrontPage: function(){
var $el = $('#apps-shelf');
if($el.visible(true) && !$el.hasClass('finished')) {
$el.addClass('finished');
$el.find('li').velocity("transition.bounceUpIn", { stagger: 150 });
} else if (!$el.visible(true) && $el.hasClass('finished')){
//other animation here
}
}
Related
As the title suggests I want to detect the start and end of a scrollable element built using overflow.
The following code works:
var scrollAmount = 150;
var scrollBox = $('.js-compare_scroll');
var arrowLeft = $('.js-compare_scroll_left');
var arrowRight = $('.js-compare_scroll_right');
var inactive = 'm-inactive';
$(arrowLeft).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '-='+scrollAmount
}, function() {
arrowRight.removeClass(inactive);
if(scrollBox.scrollLeft() === 0) {
arrowLeft.addClass(inactive);
}
});
});
$(arrowRight).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '+='+scrollAmount
}, function() {
arrowLeft.removeClass(inactive);
if(scrollBox.scrollLeft() + scrollBox.innerWidth() >= scrollBox[0].scrollWidth) {
arrowRight.addClass(inactive);
}
});
});
However the class to style the inactive colour of the arrows only appears once the animation completes. I need to add the class before the animation completes because it has a delay. I believe by default it is 400.
Is there anyway to detect this and apply the arrow classes where needed?
Thanks.
Came back from a break and realised I should take the checking if its at the end off the click event and onto a scroll event. This works a lot better now.
I am trying to replicate the scrolling effect from here: http://www.altisliferpg.com/
I have a feeling that they are using a heavily modified version of Bootstrap Navbar, which I have taken from here: http://www.enjin.com/forums/page/1/m/10826/viewthread/8514993-boot-strap-30-navbar-full-module and have changed it to fit into my specific case.
How would I make it so when you scroll down the page, the bar on the top gets "smaller" and scrolls along with the page as you scroll? Thanks
You can use css transitions for the height, font size and whatever else you want changed. Then simply set a scroll listener, which adds a class to the header so the size changes. Quick (and very ugly) example. jsFiddle
$(window).scroll(function () {
if ($(this).scrollTop()) {
$('#header').addClass('small');
}
else {
$('#header').removeClass('small');
}
});
Maybe you should detect the scroll event of the window, after that, set the position of the navbar to fixed and then, perform the animation. Here's an example of the javascript part and a link see it in action:
$(function(){
var performingDownAnimation = false,
performingUpAnimation = false;
var performScroll = function(){
if($("body").scrollTop() > 0) {
if(performingUpAnimation) {
$('#logo').stop();
performingUpAnimation = false;
}
if(!performingDownAnimation){
$('#navbar').addClass('navbar-fixed');
$('#logo').animate({ 'font-size': "12px" }, 1000, function(){
performingDownAnimation = false;
});
performingDownAnimation = true;
}
}else if($("body").scrollTop() == 0){
if(performingDownAnimation) {
$('#logo').stop();
performingDownAnimation = false;
}
if(!performingUpAnimation){
$('#navbar').removeClass('navbar-fixed');
$('#logo').animate({ 'font-size': "48px" }, 1000, function(){
performingUpAnimation = false;
});
performingUpAnimation = true;
}
}
}
$(document).on('scroll', performScroll);
});
On scroll event and position fixed
I edited my response for adding support for the "up" direction too. About using bootstrap for the animation, I have no idea how to do it, and I think it can't be done, because bootstrap is based mainly on applying CSS classes to different elements. CSS classes are discrete, but you are asking for animating something numerical, as the font-size property is. As much, you could create an animation that looks "staggered".
I am trying to change css styles as a user scrolls down and set them back to how they were when the user scrolls back to the top.
$(window).on( 'scroll', function(){
if ($(window).scrollTop() > 0) {
$('#mainMenu').animate({marginTop: '15px'},300);
$('#phoneNumber').animate({opacity: '0'},300);
$('#mainNav').addClass("mainNavScroll");
} else {
$('#mainMenu').animate({marginTop: '70px'},300);
$('#phoneNumber').animate({opacity: '1'},300);
$('#mainNav').removeClass("mainNavScroll");
}
});
It does the top part of the code (the first "if" section) fine but when I scroll back up to the top, I have problems with the "else" code. It does the last line right away (removes .mainNavScroll from #mainNav) and then waits about a minute to do the rest of the code (animations for #mainMenu and #phoneNumber).
I think this is what you want:
var top = true;
$(window).on( 'scroll', function(){
if ($(window).scrollTop() > 0) {
if (top) {
top = false;
$('#mainMenu').stop().animate({marginTop: '15px'},300);
$('#phoneNumber').stop().animate({opacity: '0'},300);
$('#mainNav').stop().addClass("mainNavScroll");
}
} else if (!top) {
top = true;
$('#mainMenu').animate({marginTop: '70px'},300);
$('#phoneNumber').animate({opacity: '1'},300);
$('#mainNav').removeClass("mainNavScroll");
}
});
The .stop()'s will stop any animation that is currently running before running the next. This will prevent queues where animations wait for each other.
The top var is to prevent the non-top animations from being triggered thousands of times while scrolling.
If you want the class added/removed after the animations are complete, you can use a callback like this:
$('#mainMenu').animate({marginTop: '70px'},300, function() {
$('#mainNav').removeClass("mainNavScroll");
});
I am writing a basic code for an animation on click with Snap.svg. It looks like this:
var s = Snap(500, 500);
var circle = s.rect(100,100,100,100);
circle.click(function(){
var width = circle.attr('width');
var height = circle.attr('height');
circle.animate({
width: width/2,
height :height/2
}, 2000);
});
I make a rectangle in the top left corner of the container and animate it's width on a click. THEN, however, I want to do something different on the second click, return it to its original state for example.
I'd also be glad to learn how do you handle this second click in Javascript in general.
For example: press this button once and the slide navigation opens. Tap it second time and the navigation dissappears.
Thanks in advance!
You can do that by using the event.detail property. In your case, that would be:
circle.click(function(e) {
var width = circle.attr('width');
var height = circle.attr('height');
if (e.detail == 1) {
circle.animate({
width: width/2,
height :height/2
}, 2000);
} else if (e.detail == 2) {
circle.animate({ //example
width:width,
height:height
}, 2000);
}
});
There, the animation to change back to the original sizes plays when the user performs a double click (so 2x fast). If you basically want to toggle the element, instead of reverting it on doubleclick, you can simply check if the element has a width or height style other than its initial width or height:
circle.click(function(e) {
var width = circle.attr('width');
var height = circle.attr('height');
if (parseInt(this.style.width) == parseInt(width) || !this.style.width) {
circle.animate({
width: width/2,
height :height/2
}, 2000);
} else {
circle.animate({ //example
width:width,
height:height
}, 2000);
}
});
Then the if() will return true when either the width attribute is equal to the width style, or when the width style is empty/not defined.
You'd want to store what state of the click.
There are many different ways to go about this, but I'll choose two:
Create a counter variable (say, counter) and increment it each time the click handler runs. Then, each time, to decide what to do, see if the number is even or odd:
var counter = 0;
circle.click(function(){
if(counter % 2 == 0){
//action1
}else{
//action2
}
counter++;
});
Alternatively, you can use a Boolean that changes each time to keep track of which action to perform.
var flag = true;
circle.click(function(){
if(flag){
//action1
flag = false;
}else{
//action2
flag = true;
}
});
This is a follow-up post to a previous question: jQuery - scroll down every x seconds, then scroll to the top
I have refined the scrip a little further, but am having a little trouble with the last step.
I have a div that automatically 50px at a time until it reaches the bottom, at which point it scrolls to the top and starts again. I have this working perfectly thanks to the above question and with a little add work.
I need to make all scrolling stop when the div is hovered. I have done part of this already (there is no incremental scrolling down on hover) but I cannot get the full picture. The div will still scroll to the top even when hovered.
Here is my jQuery and a fiddle to go along with it: http://jsfiddle.net/wR5FY/1/
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 3000);
function scrollit() {
if(scrollingUp == 0 && dontScroll == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
$('#scroller').bind('scroll', function () {
if (dontScroll == 0) {
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').delay(2000).animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
}
}
});
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});
In the fiddle, try hovering the scroller div when the yellow square is visible. You will see that it scrolls to the top.
A couple of notes:
You will notice I have used mouseenter and mouseleave rather than hover and mouseout. This was the best way I could find to ensure all child elements within the div didn't have an adverse affect.
A potential problem area is the fact that I have binded to the scroll event for my function that scrolls to the top. I think this might cause some additional problems when a user is manually scrolling through the items, with my jQuery trying to scroll against the user.
I did a little experimenting with killing setInterval, but I didn't find this to be very helpful as the function that triggers isn't the problem area.
My overall goal here is to lock down all automatic scrolling when a user is hovering or manually scrolling through the list. This is 90% there. If they happen to scroll to the bottom, NOTHING should happen until they move the mouse elsewhere - this is the problem.
Keep it easier ;)
The problem was that you first evaluate wheter dontScroll is zero, then start the timer.
When the timer has ended, it doesnt evaluate anymore, whether dontScroll STILL is zero.
Just pulled that into your scrollIt function:
var scrollingUp = 0;
var dontScroll = 0;
window.setInterval(scrollit, 2000);
function scrollit() {
if(dontScroll == 0){
if ($('#scroller').scrollTop() + $('#scroller').innerHeight() >= $('#scroller')[0].scrollHeight) {
scrollingUp = 1;
$('#scroller').animate({ scrollTop: 0 }, 1000, function() {
scrollingUp = 0;
});
} else if(scrollingUp == 0) {
$('#scroller').animate({ scrollTop: $("#scroller").scrollTop() + 50 }, 'slow');
}
}
}
$('#scroller').bind('mouseenter', function() {
dontScroll = 1;
});
$('#scroller').bind('mouseleave', function() {
dontScroll = 0;
});