0

The closest solution I found is Show div on scrollDown after 800px.

I'm learning HTML, CSS, and JS, and I decided to try to make a digital flipbook: a simple animation that would play (ie, load frame after frame) on the user's scroll.

I figured I would add all the images to the HTML and then use CSS to "stack them" in the same position, then use JS or jQuery to fade one into the next at different points in the scroll (ie, increasing pixel distances from the top of the page).

Unfortunately, I can't produce the behavior I'm looking for.

HTML (just all the frames of the animation):

<img class="frame" id="frame0" src="images/hand.jpg">
<img class="frame" id="frame1" src="images/frame_0_delay-0.13s.gif">

CSS:

body {
        height: 10000px;
}
.frame {
    display: block;
    position: fixed;
    top: 0px;
    z-index: 1;
    transition: all 1s;
}
#hand0 {
    padding: 55px 155px 55px 155px;
    background-color: white;
}
.frameHide {
  opacity: 0;
  left: -100%;
}
.frameShow {
  opacity: 1;
  left: 0;
}

JS:

frame0 = document.getElementById("frame0");

var myScrollFunc = function() {
  var y = window.scrollY;
  if (y >= 800) {
    frame0.className = "frameShow"
  } else {
    frame0.className = "frameHide"
  }
};

window.addEventListener("scroll", myScrollFunc);
};
Community
  • 1
  • 1
wwlbjd
  • 1
  • 1

2 Answers2

0

One of your bigger problems is that setting frame0.className = "frameShow" removes your initial class frame, which will remove a bunch of properties. To fix this, at least in a simple way, we can do frame0.className = "frame frameShow", etc. Another issue is that frame0 is rendered behind frame1, which could be fixed a variety of ways. ie. Putting frame0's <img> after frame1, or setting frame0's CSS to have a z-index:2;, and then setting frame0's class to class="frame frameHide" so it doesn't show up to begin with. I also removed the margin and padding from the body using CSS, as it disturbs the location of the images. I have made your code work the way I understand you wanted it to, here is a JSFiddle.

Zenny
  • 181
  • 8
0

It depends on your case, for example, in this jsFiddle 1 I'm showing the next (or previous) frame depending on the value of the vertical scroll full window.

So for my case the code is:

var jQ = $.noConflict(),
  frames = jQ('.frame'),
  win = jQ(window),

// this is very important to be calculated correctly in order to get it work right
// the idea here is to calculate the available amount of scrolling space until the
// scrollbar hits the bottom of the window, and then divide it by number of frames
  steps = Math.floor((jQ(document).height() - win.height()) / frames.length),

// start the index by 1 since the first frame is already shown
  index = 1;

win.on('scroll', function() {

  // on scroll, if the scroll value equal or more than a certain number, fade the 
  // corresponding frame in, then increase index by one.
  if (win.scrollTop() >= index * steps) {
    jQ(frames[index]).animate({'opacity': 1}, 50);
    index++;

  } else {

    // else if it's less, hide the relative frame then decrease the index by one
    // thus it will work whether the user scrolls up or down
    jQ(frames[index]).animate({'opacity': 0}, 50);
    index--;
  }
});

Update:

Considering another scenario, where we have the frames inside a scroll-able div, then we wrap the .frame images within another div .inner.

jsFiddle 2

var jQ = $.noConflict(),
  cont = jQ('#frames-container'),
  inner = jQ('#inner-div'),
  frames = jQ('.frame'),
  frameHeight = jQ('#frame1').height(),
  frameWidth = jQ('#frame1').width() + 20, // we add 20px because of the horizontal scroll
  index = 0;

// set the height of the outer container div to be same as 1 frame height
// and the inner div height to be the sum of all frames height, also we
// add some pixels just for safety, 20px here
cont.css({'height': frameHeight, 'width': frameWidth});
inner.css({'height': frameHeight * frames.length + 20});

cont.on('scroll', function() {
  var space = index * frameHeight;
  if (cont.scrollTop() >= space) {
    jQ(frames[index]).animate({'opacity': 1}, 0);
    index++;
  } else {
    jQ(frames[index]).animate({'opacity': 0}, 0);
    index--;
  }
});

** Please Note that in both cases all frames must have same height.

Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
  • Got it. I'll try these approaches instead. Thank you!! – wwlbjd Aug 03 '16 at 19:19
  • Hi Mi-Creativity! Thanks again for your help here: your second fiddle doesn't seem to be working, but the first one not only works but exhibits the exact behavior I'm trying to achieve. And while the JS/jQ is a bit beyond me to author, I can follow your approach. However, when I try it myself and replace the images with the ones I want to animate, it doesn't work... I also tried hard coding the # of steps. You can see my attempt here: https://github.com/wwlbjd/wwlbjd.github.io/blob/master/mmmessage%202/mmm2.html Any idea what might be wrong? Thanks again! – wwlbjd Aug 05 '16 at 04:59
  • @wwlbjd, hi, this is the first example but I replaced the demo images with your images, please have a look at this [demo fiddle](https://jsfiddle.net/6t3dfgLa/2/) – Mi-Creativity Aug 05 '16 at 05:26
  • and the second fiddle does work, but you need to use the scroll of the container div itself not the scrollbar of the whole document – Mi-Creativity Aug 05 '16 at 05:27
  • You welcome and I'm glad it helped, you may consider checking this as the correct answer and/or upvoting it if you want, enjoy coding! – Mi-Creativity Aug 06 '16 at 05:04