简体   繁体   中英

Delay CSS animations in chain, when visible on viewport

I have this jfiddle where:

  1. CSS animation starts when the div is on viewport.
  2. I have an unknown number of div with an Icon, and 2 text lines.

What I need:

  1. Each icon animated with a delay, with respect to the next one. In my jsfiddle all icons are animated simultaneously.

  2. The actual program might have 1, 2, or 300 divs with an icon, the solution must work for any number, not only with the 3 items of my jsfiddle example.

  3. I have bootstrap on divs , and with the scroll control, the animation only starts if the div appears on viewport, whilst on a notebook I get displayed 6 icons in a row, on a smartphone only 1.

var $animation_elements = $('.animation-element');
var $window = $(window);

function check_if_in_view() {
    var window_height = $window.height();
    var window_top_position = $window.scrollTop();
    var window_bottom_position = (window_top_position + window_height + 15);

    $.each($animation_elements, function() {
        var $element = $(this);
        var element_height = $element.outerHeight();
        var element_top_position = $element.offset().top;
        var element_bottom_position = (element_top_position + element_height);

        //check to see if this current container is within viewport
        if ((element_bottom_position >= window_top_position) &&
           (element_top_position <= window_bottom_position)) {
              $element.addClass('in-view');
        else {
              $element.removeClass('in-view');
    }
});
$window.on('scroll resize', check_if_in_view);
$window.trigger('scroll'); 
  1. The function to set a delayed action in JavaScript is setTimeout() , with it you can set one(in this case) delayed action per element (each iteration). However inside for loops, you cannot access to external variables in realtime inside setTimeout(), so you need to do it through a closure ( ref1 , ref2 ):

     (function(delay, $element, savedtimeout) { // 'savedtimeout'(alias of timeouts) is accessible. // but 'timeouts'(external var) is not accessible in realtime. savedtimeout[i][0] = setTimeout(function() { //Start animation $element.removeClass('paused'); countInView--; }, delay, timeouts); })(delay, $element, timeouts); 

    In order to delete a delayed action for a specific icon, you have to assign its returning ID to a variable, then you can interrupt its execution with the given ID using removeTimeout(ID) :

     timeouts[i][0] = setTimeout(); // Returns an unique ID clearTimeout(timeouts[i][0]); 
    • You can check my other post to see how to manage and save a timeout ID for each icon.
    • The function you are using $.each cannot be reset to 0 its index, so it gives much less options for future implementations. I would rather replace with a for loop, taking advantage of its index.
  2. The more you narrow the div width, the more divs your smartphone will be able to display. So you have to prefix the width, otherwise it seems like each div will cover all the width on your device's screen:

     .slide-left { width: 150px; /* eg */ } 

Altogether solution : https://jsfiddle.net/quq2q9cg/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM