【问题标题】:Animate position of div on scroll positiondiv 在滚动位置上的动画位置
【发布时间】:2025-12-29 03:15:06
【问题描述】:

在滚动位置设置 div 位置动画的最佳方式是什么?本质上,当您到达页面上的某个点时……一个固定的元素会动画起来。

我已经在下面包含了我目前拥有的内容...但它有点慢,似乎在向上滑动...慢慢...中途...然后完成。有什么想法吗?

var shareHeight = $('.related-share-container').height();
$('.related-share-container').css('bottom',-shareHeight);
$(window).scroll(function() {   
     if ($(window).scrollTop() + $(window).height() > $(document).height() - 150) {
        $('.related-share-container').stop().animate({ bottom: 0 }, 500);
     } else {
         $('.related-share-container').stop().animate({ bottom: -shareHeight }, 500);
     }
});

奖励更新

这是我正在开发的开发网站:http://goo.gl/KcFdE6,如您所见,如果您滚动到底部并停止,它会很好地向上滑动,但是,如果您继续滚动......它正在与动画,您可以进行非常跳跃/缓慢的过渡。有什么想法吗?

【问题讨论】:

  • 这可能会有所帮助:*.com/a/15800696/1947286
  • 你能在 jsFiddle 或其他上做一个工作示例吗?“它有点慢”是什么意思
  • @web-tiki 请查看开发网站的更新...
  • 复制时遇到问题,我看到 div 向上滚动,这很慢,但是当我到达特定点时,第二个元素会向上滑动吗?你能发布 jsfiddle 吗?

标签: javascript jquery html css animation


【解决方案1】:

发生这种情况的原因是每次滚动移动之前的动画都会停止并开始新的动画,这比之前的动画慢,因为它的动画距离更短。因此,您需要在代码中添加一些标志来防止一次又一次地触发相同的动画。

修改后的JS:

这里我使用done 类作为标志。

var shareHeight = $('.related-share-container').height();
$('.related-share-container').css('bottom',-shareHeight);
$(window).scroll(function() {   
     if ($(window).scrollTop() + $(window).height() > $(document).height() - 150) {
         if(!$('.related-share-container').hasClass('done'))
             $('.related-share-container').addClass('done').stop().animate({ bottom: 0 }, 500);
     } else {
         if($('.related-share-container').hasClass('done'))
             $('.related-share-container').removeClass('done').stop().animate({ bottom: -shareHeight }, 500);
     }
});

【讨论】:

    【解决方案2】:

    如果我理解正确,您希望页面上某处的元素在视口的特定位置滚动。

    检查这个小提琴:http://jsfiddle.net/6bZab/11/ JS:

    var oldElemBottom;
    
    function isScrolledIntoView(elem) {
      var win = $(window),
        marginBot = 20,
        docViewTop = $(window).scrollTop(),
        docViewBottom = docViewTop + $(window).height(),
        elemTop = $(elem).offset().top,
        elemBottom = elemTop + $(elem).height();
    
      if (typeof oldElemBottom !== 'undefined'){
        elemBottom = oldElemBottom;
      }
      if ((win.scrollTop() + win.height()  - marginBot) >= elemBottom){
        oldElemBottom = elemBottom;    
        return true
      } else {
        return false
      };
    }
    

    CSS:

    #container {
      width: 100%;
      height: 1000px;
    }
    
    #elem {
      width:80px;
      height:50px;
      background:#333;
      color:#FFF;
      text-align:center;
      right: 0;
    }
    
    .first{
      background-color: green;
      height: 1000px;
    }
    
    .absolute_pos{
      position: absolute;
      top: 600px;    
    }
    

    只要 viewport + marginBot 的底部通过元素,元素就会滚动。之后它会被修复,直到它再次进入顶部。

    【讨论】:

      【解决方案3】:

      您提到了不确定的动画而不是实际的 div 放置,问题在于您的 js 代码在每次滚动时都会执行,即使您已经在制作动画。这会导致您停止动画并重新启动它。这就是您看到的动画效果缓慢和滞后的原因。

      您需要做的是跟踪您是否正在制作动画并基于此做出反应,以便动画有机会完成。

      //...
      var isAnimating = false;
      
      $(this).bind('scroll', function() {
          //jQuery does have a :animated selector as well that can handle this
          if(!isAnimating){
              isAnimating = true;
              var y = $(this).outerHeight() + api.getContentPositionY() + 600 >= api.getContentHeight();
      
              if (y) {
                  $('.related-share-container').animate({ 'margin-bottom': 0 }, { queue: false, duration: 300 }, 'slow', function(){ isAnimating = false; });
              } else {
                  $('.related-share-container').animate({ 'margin-bottom': -shareHeight - 30 }, { queue: false, duration: 300 }, 'slow', function(){ isAnimating = false; });
              }
          }
      });
      

      警告!代码未经测试,但是所需代码的近似值您需要考虑到,如果它们向上滚动,则可以停止动画并反转方向。

      【讨论】:

        【解决方案4】:

        先检查一下demo

        CSS

        .related-share-container{
            position: fixed;
            left: 0;
            bottom: 0;
            width: 100%;
            z-index: 9999;
            padding: 15px 0;
            font-size: 16px;
            display:none;
        }
        

        下载animate.css文件并链接到您的文件

        JS

        $(window).scroll(function(e) {
                if ($(window).scrollTop() + $(window).height() > $(document).height() - 150) {
                    $('.related-share-container').removeClass('rotateOutUpLeft').addClass('animated rotateInUpLeft').show();
                } else {
                    $('.related-share-container').removeClass('rotateInUpLeft').addClass('rotateOutUpLeft');
                }
            });
        

        它的工作完美。不要忘记下载 animate.css 文件并添加到您的站点。你可以选择动画效果。

        【讨论】:

          【解决方案5】:

          你有两个选择,两个都不错,但后者更好:

          A.使用 debounced 函数 - 换句话说,您希望限制滚动侦听器,使其每 X 毫秒仅发生一次,因此如果有人在中间滚动,则不会发生。

          lodash 等库将其提供为 _.debounce(fn, time);

          如果您不使用库,可以这样实现(我使用的是您当前站点的代码):

                  var shareHeight = $('.related-share-container').height();
                  $('.related-share-container').css('height',shareHeight);
                  $('.project-content-container').css('margin-bottom',shareHeight);
                  $('.related-share-container').css('margin-bottom',-shareHeight - 30);
                  var timeout,
                      elem = $(this);
                  elem.bind('scroll', function() {
                      clearTimeout(timeout);
                      timeout = setTimeout(function(){
                          var y = elem.outerHeight() + api.getContentPositionY() + 600 >= api.getContentHeight();
                          if (y) {
                              $('.related-share-container').stop(true).animate({ 'margin-bottom': 0 }, { queue: false, duration: 300 });
                          } else {
                              $('.related-share-container').stop(true).animate({ 'margin-bottom': -shareHeight - 30 }, { queue: false, duration: 300 });
                          }
                      }, 50); //50ms debounce time
                  });
          

          B.分步动画 - 换句话说,每次调用 animate 函数时,它不会对容器的完整大小进行动画处理,而只会对滚动的量(或设置的步长)进行动画处理。这实际上是一个更好的解决方案,因为目前,如果有人向下滚动并弹出巨大的页脚,几乎不可能向上滚动。 tween.js 等库让这一切变得简单。

          【讨论】:

            【解决方案6】:

            我会使用 css 过渡而不是 jquery animate,如下所示,这样您就不必担心动画队列。

            (使用css,你甚至可以使用hardware acceleration

            css

            .element-to-animate {
             /*your style rules*/
             transform: translate3d(0, 0, 0);
             transition:height .5s linear;
            }
            .hide {
             height:0 !important;
            }
            

            脚本:

            var sliderTop = $(window).height() - 150;
            $(window).scroll(function () {
             var scrollTop = $(window).scrollTop();
             if (scrollTop > sliderTop) {
                if ($('.overlay').hasClass('hide'))
                  $('.overlay').removeClass('hide');
             } else {
                if (!$('.overlay').hasClass('hide'))
                   $('.overlay').addClass('hide');
             }
            });
            

            Demo

            【讨论】: