Domanda

Hi I want to bind the the CSS opacity of two divs with how much that element is scrolled.

For example say I have two divs:

<div class="red" style="background:red"></div>
<div class="blue" style="background:blue"></div>

As the red div comes into the viewport, its opacity goes from 0 to 100 - depending on the amount scrolled.

Likewise as the blue div comes into viewport its opacity goes from 100 to 0, depending on the amount scrolled.

I found this Jquery/Javascript Opacity animation with scroll -

    var fadeStart=100 // 100px scroll or less will equiv to 1 opacity
    ,fadeUntil=200 // 200px scroll or more will equiv to 0 opacity
    ,fading = $('#fading')
;

$(window).bind('scroll', function(){
    var offset = $(document).scrollTop()
        ,opacity=0
    ;
    if( offset<=fadeStart ){
        opacity=1;
    }else if( offset<=fadeUntil ){
        opacity=1-offset/fadeUntil;
    }
    fading.css('opacity',opacity).html(opacity);
});

however the scroll amount is bound the document height, rather than the div itself.

Here is a jsfiddle to work from http://jsfiddle.net/RPmw9/

Thanks in advance.

È stato utile?

Soluzione

Depends on when you want it fully opaque or not, but this could be a start:

»»Fiddle«« (Multiple element class version - set individually)

»»Fiddle«« (Single element class version - if only one element per class)

function fader() {
    var r = $('.red'),   // The .red DIV, as variable so we do not have to look
                         // it up multiple times.
        b = $('.blue'),  // Same for blue.
        wh = $(window).height(),      // Height of window (visible part).
        dt = $(document).scrollTop(), // Pixels document is scrolled down.
        /* red offset top is a semi static values which say how many pixels it
         * is from the top of the document.
         * "Red Offset Top" - "Document Scroll Top" gives us how many pixels
         * the red DIV is from top of visible window.
         * "Window Height" - that value gives us pixels the red DIV is from top
         * normalized to start from 0 when top of DIV is at bottom of window.
         * */
        redView  = wh - (r.offset().top - dt),
        // Same for blue DIV
        blueView = wh - (b.offset().top - dt),
        // Variable to save opacity value.
        op;
    /* If redView is bigger then 0 it means the DIV has top border above bottom
     * of window. 
     */
    if (redView > 0) {
        /* Opacity goes from 0 - 1 so we divide 1 by window height and
         * multiplies it with pixels red DIV is from bottom.
         * In addition we add the height of the red DIV to window height, such
         * that we set opacity until it is out of view (Bottom border is at top
         * of window, and not only until it has top border at top of window.)
         */
        op = 1 / (wh + r.height()) * redView;
        /* If value of calulation is less or equal to one, it is in visible
         * view and we set the opacity accordingly.
         */
        if (op <= 1)
            r.css('opacity', op);
    }
    if (blueView > 0) {
        op = 1 - 1 / (wh + b.height()) * blueView;
        if (op >= 0)
            b.css('opacity', op);
    }

    // Add this line for a possible help in understanding:
    console.log(
         'Window Height:', wh, 
         'Doc Scroll Top', dt, 
         'Red offset top:', r.offset().top, 
         'Red offs.top - Doc Scroll Top', r.offset().top - dt, 
         'View:', wh - (r.offset().top - dt)
    );
}
// Attach scroll event to the function fader()
$(document).bind('scroll', fader);

OK. Added some comments. Might not feel it is the best explanation. A better way to understand it is perhaps to have a look at the values so I also added a console.log() line inside the fader() function. Open your console and view the values as you scroll. Fiddle with logging. Also note this performance difference. style is considerably faster.

Version two:

This set full opacity when element has top at top of window, (not bottom of element). Note that we could use the Math.min() in the above function as well, to omit the op variable and if (op <= 1) and if (op >= 0) statement, but not at least a quick benchmark on jsperf revealed the if version to perform slightly better. If you have many elements that you style one should use the if version.

»»Fiddle««

function fader() {
    var r = $('.red'),
        b = $('.blue'),
        wh = $(window).height(),
        dt = $(document).scrollTop(),
        redView  = wh - (r.offset().top - dt),
        blueView = wh - (b.offset().top - dt);
    if (redView > 0) {
        // Math.min() returns the lowest of given values. Here we do not want
        // values above 1.
        $('.red').css('opacity', Math.min(1 / wh * redView, 1));
    }
    if (blueView > 0) {
        $('.blue').css('opacity', 1 - Math.min(1 / wh * blueView, 1));
    }
}
// Event on scroll
$(document).bind('scroll', fader);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top