【问题标题】:Delay CSS animations in chain, when visible on viewport延迟链中的 CSS 动画,当在视口上可见时
【发布时间】:2023-03-10 15:03:01
【问题描述】:

我有this jfiddle 在哪里:

  1. CSS 动画在 div 出现在视口上时开始。
  2. 我有一个 未知 号码 div,带有一个图标和 2 个文本行。

我需要什么:

  1. 每个图标相对于下一个图标都有延迟。在我的 jsfiddle 中,所有图标都是同时动画的。

  2. 实际程序可能有 1、2 或 300 个 divs 和一个图标,解决方案必须适用于任何数字,而不仅仅是我的 jsfiddle 示例中的 3 项。

  3. 我在 divs 上有引导程序,并且使用滚动控件,动画只有在 div 出现在视口上时才会开始,而在笔记本电脑上我会连续显示 6 个图标,仅在智能手机上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'); 

【问题讨论】:

  • 您是否希望图标按顺序出现,例如,第一个结束时,第二个开始,第二个结束时,第三个开始等等?
  • 嗨@Roizpi!首先感谢您的时间!不一定按顺序 - 我在每个图标之间使用了 3 秒的延迟。但是 - 我在 div 上有引导程序,并且使用 scrool 控件,动画只有在 div 出现在屏幕上时才会开始 - 但在笔记本上我连续获得 6 个图标,而在手机上我连续只有 1 个图标。然后,动画以不同的图标结束,并以滚动重新开始。(我不知道你是否理解,如果这个细节可能有问题..)
  • 您能上传任何显示 jfiddle 的手机图片吗?这将有助于诊断。 @DANIEL 考虑这个solution 来解决上述延迟问题。
  • This 一个人解决了一个小问题
  • 嗨@Roizpi!很多!我昨天阅读了您的消息并正在测试解决方案。我遇到了一个小问题,正在创建一个新的 jfiddle 来向您展示,但现在我看到了您的新消息,并将测试新的修复程序。我很快就会回来tksssssss!

标签: javascript jquery html css animation


【解决方案1】:
  1. 在 JavaScript 中设置延迟操作的函数是 setTimeout(),您可以使用它为每个元素(每次迭代)设置一个(在这种情况下)延迟操作。 但是在 for 循环中,您无法在 setTimeout() 中实时访问外部变量,因此您需要通过闭包来实现(ref1ref2):

    (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);
    

    要删除特定图标的延迟操作,您必须将其returning ID 分配给一个变量,然后您可以使用removeTimeout(ID) 以给定ID 中断其执行:

    timeouts[i][0] = setTimeout(); // Returns an unique ID
    clearTimeout(timeouts[i][0]);
    
    • 您可以查看我的另一个post,了解如何管理和保存每个图标的超时 ID。
    • 你正在使用的函数$.eachcannot be reset to 0它的索引,所以它为未来的实现提供了更少的选择。我宁愿用for 循环替换,利用它的索引。
  2. 您将 div 宽度缩小得越多,您的智能手机将能够显示的 div 越多。 所以你必须为宽度加上前缀,否则每个 div 似乎都会覆盖设备屏幕上的所有宽度:

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

总共解决方案https://jsfiddle.net/quq2q9cg/

【讨论】:

  • 嗨@Roizpi,再次感谢您的时间和帮助!是的,我也在尝试 - 将功能重置为零.. - 那么,我同意并理解你所说的! (我不是 js 专家) - 我测试了你的新解决方案,但仍然在做同样的问题。如果你在第二行向下/向上滚动动画或创建 4、5 个新行(花更多时间完成所有图标动画并重新启动)-当您向下滚动第一个图标时仍然随机..或者如您所说,指针位于最后一个位置。我也在这里测试一些想法..但问题总是一样的。仅重置 SLIDE-LEFT 动画。
  • 经过艰苦的研究,我找到了一个解决方案。前一个具有适当的逻辑,但 removeInterval 部分并没有真正起作用。
  • @DANIEL 你去!如果有用,请考虑点赞答案,或者如果解决了您的原始问题,请将其标记为已接受。每次我回答时,你都在要求不同的实现,这很好,但这让我每次都编辑你的帖子和我的帖子,这可能是无止境的:-)。我将尝试通过评论解决新的疑问。干杯。
  • @DANIEL 该解决方案对您有帮助吗?干杯。
猜你喜欢
  • 2015-08-31
  • 1970-01-01
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
相关资源
最近更新 更多