最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - FadeIn elements on scroll - Stack Overflow

programmeradmin1浏览0评论

I have a function that at the moment, fades in elements sequentially however id like the mousewheel to control their opacity instead if its possible.

Can anybody advise on how i would do this? Would it require the mousewheel plugin? thanks for any input

/

$('.sector-link').each(function (i) {
    $(this).delay(350 * i).fadeIn(800);
});

HTML Markup

<div style="overflow:scroll;width:100%; border:0; height:300px; ">
            <div style="height:3000px; position:relative;">
                <div style="position:fixed;left:0; top:50px;">
                     sector links...
                  </div>
              </div>
          </div>

I have a function that at the moment, fades in elements sequentially however id like the mousewheel to control their opacity instead if its possible.

Can anybody advise on how i would do this? Would it require the mousewheel plugin? thanks for any input

http://jsfiddle.net/gLtgj54s/

$('.sector-link').each(function (i) {
    $(this).delay(350 * i).fadeIn(800);
});

HTML Markup

<div style="overflow:scroll;width:100%; border:0; height:300px; ">
            <div style="height:3000px; position:relative;">
                <div style="position:fixed;left:0; top:50px;">
                     sector links...
                  </div>
              </div>
          </div>
Share Improve this question edited Mar 6, 2015 at 10:16 Liam asked Mar 3, 2015 at 15:09 LiamLiam 9,85540 gold badges114 silver badges214 bronze badges 10
  • the fiddle doesnt work – m0bi5 Commented Mar 3, 2015 at 15:12
  • @MohitBhasi yes it does. Fades in on page load. – Adjit Commented Mar 3, 2015 at 15:12
  • So instead of a fully automated fadeIn, you want to adjust the opacity of each line of text based on the scroll position? – Terry Commented Mar 3, 2015 at 15:14
  • Yes that's it @Terry, I'm just unsure how this would even work? – Liam Commented Mar 3, 2015 at 15:18
  • Check out a library like Waypoints – DrColossos Commented Mar 3, 2015 at 15:19
 |  Show 5 more comments

11 Answers 11

Reset to default 11 +500

One approach is you can use data attributes to set a point when the element should fadeIn.

<div class="sector-link" data-scroll-point="100">Link 1</div>

And in JS check when the scrollTop value is in the range between the element's scroll point and the next element's scroll point.

var arr = [];
$('.sector-link').each(function(i) {
  arr.push($(this).data("scroll-point"));
});

$(window).scroll(function() {
  var scrollTop = $(window).scrollTop();
  elementFade(scrollTop);

});

elementFade = function(top) {
  for (var i = 0; i < arr.length; i++) {
    var min = arr[i];
    var max = i != (arr.length - 1) ? arr[i + 1] : (arr[i] + 100);
    if (top >= min && top < max) {
      $('[data-scroll-point="' + arr[i] + '"]').fadeIn(800);
      $('p.info').html($('[data-scroll-point="' + arr[i] + '"]').html() + " visible at point " + arr[i]);
    }
  }
}
body {
  height: 3000px;
}
p.info {
  position: fixed;
  top: 0;
  font-size: 11px;
  color: #555;
  background: #eee;
  padding: 3px;
}
.sector-link {
  float: left;
  margin: 5px;
  padding: 5px;
  border-radius: 2px;
  background: #abcdef;
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="info">Not visible</p>
<div style="position:fixed;left:0; top:50px;">
  <div class="sector-link" data-scroll-point="100">Link 1</div>
  <div class="sector-link" data-scroll-point="300">Link 2</div>
  <div class="sector-link" data-scroll-point="500">Link 3</div>
  <div class="sector-link" data-scroll-point="700">Link 4</div>
  <div class="sector-link" data-scroll-point="1000">Link 5</div>
  <div class="sector-link" data-scroll-point="1200">Link 6</div>
  <div class="sector-link" data-scroll-point="2000">Link 7</div>
  <div class="sector-link" data-scroll-point="2500">Link 8</div>
</div>

Updated fiddle

Anytime you use a mousewheel to scroll, the opacity changes to make it more or less visible. This is using the DOMMouseScroll event or the mousewheel event. See the following code:

function moveObject(event){
    var delta=0;
    if(!event)event=window.event;
    if(event.wheelDelta){
        delta=event.wheelDelta/600;
    }else if(event.detail){
        delta=-event.detail/20;
    }
    var target = $('body > div');
    var adj = parseFloat(target.css('opacity'));
    target.css('opacity',Math.max(0,Math.min(1,adj+Math.max(0.6,adj)*delta)));
}
if(window.addEventListener){
    document.addEventListener('DOMMouseScroll',moveObject,false);
}else{
    document.onmousewheel=moveObject;
}

Here's a jsFiddle to try it yourself: http://jsfiddle.net/gLtgj54s/14/

Thanks to: http://viralpatel.net/blogs/javascript-mouse-scroll-event-down-example/

You could use a library, namely scrollReveal.js, which is quite nice.

here is a Code Pen I made using the library. A simplified of this Code Pen

Your code can be as simple as:

<html>
  <body>
      <p data-scrollreveal='ease in 50px'> Thing </p>
      <p data-scrollreveal='ease in 50px'> Thing </p>
      <p data-scrollreveal='ease in 50px'> Thing </p>
      ...
  </body>
</html>

https://github.com/julianlloyd/scrollReveal.js

Due to Apple's decision to not send the "scroll" event until after it finishes scrolling I'd suggest something like this instead -

Firstly set everything to display:block, and opacity:0

var scrollTop;
var $elements = $(...);
window.setTimeout(function(){ // Better to use requestAnimationFrame if available
    if (scrollTop !== window.scrollTop) {
        scrollTop = window.scrollTop;
        for (var i=0; i<elements.length; i++) {
            var rect = elements[i].getBoundingClientRect();
            elements[i].style.opacity = Math.min(1, Math.max(0, rect.top, rect.bottom > 0 ? window.innerHeight - rect.bottom : 0) / 20);
            // ie, Put in something to control it based on the difference between the top/bottom of the element and the display
        }
    }
}, 50);

Despite this being a jQuery question - running code like this on every frame that things change can be expensive, hence I've used direct DOM code, which is significantly faster!

Heres a modified fiddle. It's not entirely clear in your question, but I assume you want the opacity set based on where the element is in the viewport.

$(document).ready(function () {
    $('.sector-pink').css({
        opacity: 0,
        visibility: 'visible'
    });

    var setOpacity = function () {
        var container = $(this);

        $('.sector-link').each(function () {
            var self = $(this);
            var fromBottom = container.height() - self.offset().top;


            var opacity = fromBottom / 100;
            //100 is a magic number that will control how far from the bottom of the viewport things become fully visible.

            self.find('span').text(opacity.toFixed(2));
            self.css({
                'opacity': opacity
            });


        });
    };
    $('#container').scroll(function () {
        setOpacity();
    });
    setOpacity();
});

If I understand you correctly, you want that when user scrolls the page down then elements fade in sequentially. (Run the code snippets to see whether this is what you want or not)

var showing = false;
$(document).scroll(function() {
  if (!showing && isElementInViewport($('.sector-link:last'))) {
    showing = true;
    $('.sector-link').each(function(i) {
      $(this)
        .delay(100 * i)
        .css('visibility', 'visible')
        .hide()
        .fadeIn(400);
    });
  }
})

// This function determines if the given element is inside the current view port
function isElementInViewport(el) {

  //special bonus for those using jQuery
  if (typeof jQuery === "function" && el instanceof jQuery) {
    el = el[0];
  }

  var rect = el.getBoundingClientRect();

  return (
    rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
    rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ );
}
body {
  height: 100000px;
}
.sector-link {
  font-size: x-small;
  visibility: hidden;
  border: 1px solid yellowgreen;
  padding: 0.1em;
  width: 120px;
  text-align: center;
  color: white;
}
div.placeholder {
  text-align: center;
  padding: 0.1em;
  height: 500px;
  width: 120px;
  background: yellowgreen;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="placeholder">Scroll down slowly</div>
<div>
  <div class="sector-link" style="background:#563895">THING</div>
  <div class="sector-link" style="background:#765835">THING</div>
  <div class="sector-link" style="background:#068865">THING</div>
  <div class="sector-link" style="background:#a468f5">THING</div>
  <div class="sector-link" style="background:#56ffab">THING</div>
  <div class="sector-link" style="background:#563895">THING</div>
  <div class="sector-link" style="background:#8f68f5">THING</div>
  <div class="sector-link" style="background:#a6b8f5">THING</div>
</div>

  1. Is that what you need ?

    JsFiddle

    var cpt = 0;
    $( window ).scroll(function() {
       $('.sector-link:eq('+cpt+')').fadeIn(800);
       cpt = cpt + 1;
    });
    

    I removed delay(350) on the jsfiddle, but you can put it back if needed : JsFiddle

  2. I don't know if you need it, but if so, there is some code JsFiddle (not perfect) that does what you want, plus the reverse.

    • On scroll down : Your THING appear one after each other
    • On scroll up : Your THING disappear one after each other

You can simply use Twitter Bootstrap's Scrol Spy, and not try to reinvent the wheel. To achieve the desired behavior with it, just follow the instructions and add the following css:

.active ~ li {
    opacity: 0;
    transition: 1s;
}

By the way, you can also try it there. Open the linked website, add the snippet on console, and scroll through the documentation.

So here is my solution to the problem:

Items that have a class of .sectrol-link fade out or in one by one based on how you scroll.

In order for this method to work you dont have to have an actual scrollbar. The solution doesnt keep track of the scroll position, it is based on the 'scrollwheel' event.

It also fades out the elements when scrolling up.

I am sure you can tweak the solution to match your needs.

   // Constants
var pxPerItem = 720;
var sectorLinks = $('.sector-link');
var scrollYMax = sectorLinks.length * pxPerItem;

//Fade controller variable
var currentScrollY = 0;


//Calculates fade value for the item based on current 'scroll' position
function calculateFade(itemNo) {
    var relativeScroll = (currentScrollY - pxPerItem * itemNo) / pxPerItem;
    return Math.min(Math.max(0, relativeScroll), 1)
}

//Keeps the controller scroll variable within the bounds based on the amount of elements. 
function normalizeCurrentScroll() {
    currentScrollY = Math.min(Math.max(0, currentScrollY), scrollYMax);
}

//The actual event that controls items fade
$(window).bind('mousewheel DOMMouseScroll', function(event){
    var delta = event.originalEvent.wheelDelta == 0 ? event.originalEvent.detail : event.originalEvent.wheelDelta;
    currentScrollY -= delta;
    for (var i = 0; i < sectorLinks.length; i++) {
        $(sectorLinks[i]).fadeTo(20, calculateFade(i));
    }    
    normalizeCurrentScroll();
});

The amount of wheel scrolling needed to fade in or fade out the link is controlled by 'pxPerItem' variable. If you want to place such a thing somehere down below on your page, you would have to tweak scrollYMax variable and calculateFadeFunction so that they match your height.

Fiddle: https://jsfiddle.net/gLtgj54s/18/

I've used this successfully to accomplish what you are looking to do:

$(window).bind("scroll", function() {  
    if ($(this).scrollTop() > 800) { //Fade in at a level of height
        $(".XX").fadeIn("fast");  
        checkOffset(); //Call function
    } else {  
        $(".XX").stop().fadeOut("fast");  
    }  
});  
function checkOffset() {  
    if ($('.XX').offset().top + 500 + $('#myDiv').height() >= $('.Container').offset().top) {  
        $(".XX").stop().fadeOut("fast");
    }  
    if ($(window).scrollTop() + $(window).height() < $('.Container').offset().top) {  
        $('.XX').css('position', 'fixed'); //Restore when you scroll up  
    }  
}

I've updated your fiddle, hopefully this is what you were looking for?

This just uses .fadeIn / .fadeOut on each element depending on the scroll position

for example:

if ( $(document).scrollTop() > 50 ) {
    $('#2').fadeIn(800);     
} else {
    $('#2').fadeOut(800); 
}
发布评论

评论列表(0)

  1. 暂无评论