8

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>
Liam
  • 9,725
  • 39
  • 111
  • 209
  • the fiddle doesnt work – m0bi5 Mar 03 '15 at 15:12
  • @MohitBhasi yes it does. Fades in on page load. – Adjit Mar 03 '15 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 Mar 03 '15 at 15:14
  • Yes that's it @Terry, I'm just unsure how this would even work? – Liam Mar 03 '15 at 15:18
  • Check out a library like [Waypoints](https://github.com/imakewebthings/waypoints) – DrColossos Mar 03 '15 at 15:19
  • Try this: http://stackoverflow.com/questions/10203777/div-opacity-based-on-scrollbar-position – Derek Story Mar 03 '15 at 15:19
  • Thanks @dwreck08 but all my elements are floated left on my website so then they would fade in at the same time as they all come in to view at the same time, thanks for the input though – Liam Mar 03 '15 at 15:34
  • Does [my answer](http://stackoverflow.com/a/28883772/3974585) helped you ? Tell me if something is missing – Romain Derie Mar 05 '15 at 17:32
  • Don't forget that any answers using ```.scroll(...)``` or ```.on("scroll", ...)``` fail completely on iOS devices where the scroll event is only sent once at the end of scrolling - mouse/touch handling events work, but are non-standard (they're getting there slowly thankfully), so polling the scrollTop is the only guaranteed way to work - a combined answer using scroll/mousewheel events on desktop and polling would be ideal, but harder to maintain... – Rycochet Mar 06 '15 at 14:12
  • are you looking for this [http://jsfiddle.net/Marcel/BP6rq/](http://jsfiddle.net/Marcel/BP6rq/) – TechnoCrat Mar 12 '15 at 17:26

11 Answers11

11

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

anpsmn
  • 7,217
  • 2
  • 28
  • 44
  • Thanks for this @Anpsmn, my markup is in a div however, how would it work with scrolltop? ive updated my question... – Liam Mar 06 '15 at 10:15
  • @Liam You can bind the scroll event from window to the div container like [this](http://jsfiddle.net/s7mufpzv/). Hope this is what you want. – anpsmn Mar 06 '15 at 10:23
  • Thanks @Anpsmn, is their a way to fade them out when you scroll up? ill award the bounty in 6 hours (soonest i can do it!)... – Liam Mar 06 '15 at 10:29
  • Don't forget that this doesn't work on iOS where the scroll event is only sent once after scrolling (and the momentum scrolling effect) has finished... – Rycochet Mar 12 '15 at 13:31
1

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/

Pluto
  • 2,900
  • 27
  • 38
0
  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
Romain Derie
  • 516
  • 7
  • 17
0

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); 
}
falsarella
  • 12,217
  • 9
  • 69
  • 115
Pixelomo
  • 6,373
  • 4
  • 47
  • 57
0

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

cpk
  • 809
  • 1
  • 6
  • 20
0

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!

Rycochet
  • 2,860
  • 1
  • 22
  • 39
0

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();
});
Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75
0

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>
frogatto
  • 28,539
  • 11
  • 83
  • 129
0

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.

falsarella
  • 12,217
  • 9
  • 69
  • 115
0

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/

MarengoHue
  • 1,789
  • 13
  • 34
0

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  
    }  
}
falsarella
  • 12,217
  • 9
  • 69
  • 115
chroix
  • 1
  • 1