phew phew - 5 months ago 13
Javascript Question

How do I achieve a fully working image scrolling effect like in this example?

I just stumbled upon http://www.newego.de/ and would like to know how the "image slide effekt" they are using on the initial page is done.

When you scroll up the background image changes and after you went through all their "intro/welcome"-page slides you are guided to the main website content.

I tried replicating the effect out of curiosity and for learning purposes, hence I recently started digging into responsive webdesign, but I'm kind of stuck and not sure if my approach is a good solution.

This JSFiddle is how far I've come attempting to replicate the image slider.



$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
console.log('scrolling down');
}
else {
console.log('scrolling up');
$('.s1').slideUp('slow');
}
});

* { margin: 0; padding: 0 }

#menubar {
width: 100%;
background-color: orange;
height: 60px;
}

.slide {
position: absolute;
width: 100%;
top: 60px;
bottom: 0;
}
.slide.s1 { background-color: green; }
.slide.s2 { background-color: red; }
.slide.s3 { background-color: cornflowerblue; }

.l1 { z-index: 3; }
.l2 { z-index: 2; }
.l3 { z-index: 1; }

<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>

<html>
<body>
<header id="menubar"><p>hi im a header</p></header>
<section class="slide s1 l1"><p>im the first</p></section>
<section class="slide s2 l2"><p>im the second</p></section>
<section class="slide s3 l3"><p>im the third</p></section>
</body>
</html>





My thinking was to just put three
.slide
container which fill in the "empty viewport space" on top of each other, using a hierarchy of
z-index
and then just slide up the topmost
.slide
container using jQuery's
.slideUp()
function.

However, I'm not sure if that is a good aproach as I do not know how to select the topmost container to be able to fade it out.

Is there a more simple (and if possible more modular) approach that I should pursue? Is there an effective way (jQuery/CSS selector) to find the topmost
.slide
-layer that is currently visible?

Answer

Here's the JSFiddle for the effect you were going for: https://jsfiddle.net/d1xzc4jf/7/

Here's the relevant jQuery code:

$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) 
  {
    console.log('scrolling down');
    if ($('.s2').is(':visible')) { $('.s3').slideDown('slow'); }
    else if ($('.s1').is(':visible')) { $('.s2').slideDown('slow'); }
  }
  else 
  {
    console.log('scrolling up');
    if ($('.s3').is(':visible')) { $('.s3').slideUp('slow'); }
    else if ($('.s2').is(':visible')) { $('.s2').slideUp('slow'); }        
  }
});

One approach would be to place all divs and set their display property to none except for the one to currently display. This is what happens to an item once it is done sliding up from the jQuery slideUp function. You could check to see which one is visible and have it hide while the next one is being displayed using whatever method you like.

UPDATE:

The reason the double-slideUp happens when double-scrolling, but not a double-slideDown is because the visible property is set at the beginning of a slideDown, but it is set at the end of a slideUp.

To prevent the double-slideUp effect from hard scrolling, set a variable to indicate an animation is busy when you start an animation and use a callback function to set the variable to not busy when the animation finishes, like this:

First, put this at the bottom of your page:

<script> var isbusy = 0; </script>

Then use this code for your scroll function:

$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
    console.log('scrolling up');
    if ($('.s2').is(':visible')) { 
        if (isbusy == 0) 
        {
            isbusy = 1;
            $('.s3').slideDown('slow', function() {
                isbusy = 0;
            })                
        }
    } 
    else 
    {            
        if ($('.s1').is(':visible')) 
        { 
            if (isbusy == 0)
            {
                isbusy = 1;
                $('.s2').slideDown('slow', function(){
                    isbusy = 0;
                });
            }
        }           
    }
}
else 
{
    console.log('scrolling down');
    if ($('.s3').is(':visible')) 
    {
        if (isbusy == 0) 
        {
            isbusy = 1;
            $('.s3').slideUp('slow', function(){
                isbusy = 0;
            }); 
        }
    }
    else if ($('.s2').is(':visible')) 
    {
        if (isbusy == 0)
        {
            isbusy = 1;
            $('.s2').slideUp('slow', function(){
                isbusy = 0;
            });
        }
    }
  }
});

The reason this code works is that the callback functions are executed when the animation finishes, while the next line of code is executed immediately, before the animation finishes, so the isbusy = 1; is executed before the animation finishes, while the isbusy = 0; in the callback function is executed after the animation finishes, even though it is shown in the code before the isbusy = 1; line.