首页 文章

Animate scrollTop无法在firefox中运行

提问于
浏览
163

这个功能很好 . 它将主体滚动到所需容器的偏移量

function scrolear(destino){
    var stop = $(destino).offset().top;
    var delay = 1000;
    $('body').animate({scrollTop: stop}, delay);
    return false;
}

但不是在Firefox中 . 为什么?

-编辑-

要在接受的答案中处理de double触发器,我建议在动画之前停止元素:

$('body,html').stop(true,true).animate({scrollTop: stop}, delay);

11 回答

  • 0

    对我来说,它避免在动画点附加ID:

    避免:

    scrollTop: $('#' + id).offset().top
    

    事先准备id并改为:

    scrollTop: $(id).offset().top
    

    固定在FF . (css添加对我没有影响)

  • 6
    setTimeout(function(){                               
                       $('html,body').animate({ scrollTop: top }, 400);
                     },0);
    

    希望这有效 .

  • 0

    对我来说问题是firefox自动跳转到具有name-attribute的锚点与我放入URL的哈希名称相同 . 即使我放了.preventDefault()来防止这种情况 . 因此在更改名称属性后,firefox不会自动跳转到锚点,而是正确执行动画 .

    @Toni对不起,如果这是不可理解的 . 问题是我更改了URL中的哈希值,如www.someurl.com/#hashname . 然后我有一个像 <a name="hashname" ...></a> 这样的锚点,jQuery应该自动滚动到它 . 但它没有,因为它在Firefox中没有任何滚动动画的情况下直接跳转到具有匹配名称属性的锚点 . 一旦我将name属性更改为与散列名称不同的内容,例如更改为 name="hashname-anchor" ,滚动就会起作用 .

  • 2

    Firefox将溢出放在 html 级别,除非特别设计为不同的行为 .

    要使其在Firefox中运行,请使用

    $('body,html').animate( ... );
    

    Working example

    CSS解决方案是设置以下样式:

    html { overflow: hidden; height: 100%; }
    body { overflow: auto; height: 100%; }
    

    我认为JS解决方案的侵入性最小 .


    Update

    下面的大量讨论集中在这样一个事实,即动画两个元素的 scrollTop 会导致回调被调用两次 . 浏览器检测功能已被建议并随后弃用,有些可能相当牵强 .

    如果回调是幂等的并且不需要大量的计算能力,那么两次触发可能是完全没有问题的 . 如果回调的多次调用确实是一个问题,并且如果您想避免特征检测,则可能更直接地强制回调仅在回调中运行一次:

    function runOnce(fn) { 
        var count = 0; 
        return function() { 
            if(++count == 1)
                fn.apply(this, arguments);
        };
    };
    
    $('body, html').animate({ scrollTop: stop }, delay, runOnce(function() {
       console.log('scroll complete');
    }));
    
  • 329

    在单个受支持的对象上进行特征检测和动画制作会很不错,但是没有单线解决方案 . 与此同时,这是一种使用promise来执行单个回调的方法 .

    $('html, body')
        .animate({ scrollTop: 100 })
        .promise()
        .then(function(){
            // callback code here
        })
    });
    

    更新:以下是您可以使用特征检测的方法 . 在动画调用之前,需要对这块代码进行评估:

    // Note that the DOM needs to be loaded first, 
    // or else document.body will be undefined
    function getScrollTopElement() {
    
        // if missing doctype (quirks mode) then will always use 'body'
        if ( document.compatMode !== 'CSS1Compat' ) return 'body';
    
        // if there's a doctype (and your page should)
        // most browsers will support the scrollTop property on EITHER html OR body
        // we'll have to do a quick test to detect which one...
    
        var html = document.documentElement;
        var body = document.body;
    
        // get our starting position. 
        // pageYOffset works for all browsers except IE8 and below
        var startingY = window.pageYOffset || body.scrollTop || html.scrollTop;
    
        // scroll the window down by 1px (scrollTo works in all browsers)
        var newY = startingY + 1;
        window.scrollTo(0, newY);
    
        // And check which property changed
        // FF and IE use only html. Safari uses only body.
        // Chrome has values for both, but says 
        // body.scrollTop is deprecated when in Strict mode.,
        // so let's check for html first.
        var element = ( html.scrollTop === newY ) ? 'html' : 'body';
    
        // now reset back to the starting position
        window.scrollTo(0, startingY);
    
        return element;
    }
    
    // store the element selector name in a global var -
    // we'll use this as the selector for our page scrolling animation.
    scrollTopElement = getScrollTopElement();
    

    现在使用我们刚刚定义的var作为页面滚动动画的选择器,并使用常规语法:

    $(scrollTopElement).animate({ scrollTop: 100 }, 500, function() {
        // normal callback
    });
    
  • 1

    我花了很多年时间试图弄清楚为什么我的代码不起作用 -

    $('body,html').animate({scrollTop: 50}, 500);
    

    问题出在我的CSS中 -

    body { height: 100%};
    

    我把它设置为 auto (并且担心为什么它首先被设置为 100% ) . 这为我解决了这个问题 .

  • -8

    您可能想通过使用插件来回避问题 - 更具体地说,my plugin :)

    说真的,尽管基本问题早已得到解决(不同的浏览器使用不同的元素进行窗口滚动),但是有很多非常重要的问题会让你感到沮丧:

    我显然有偏见,但jQuery.scrollable实际上是解决这些问题的不错选择 . (事实上,我不知道任何其他处理它们的插件 . )

    此外,您可以使用the getScrollTargetPosition() function in this gist以防弹方式计算目标位置 - 您滚动到的目标位置 .

    所有这些都会让你失望

    function scrolear ( destino ) {
        var $window = $( window ),
            targetPosition = getScrollTargetPosition ( $( destino ), $window );
    
        $window.scrollTo( targetPosition, { duration: 1000 } );
    
        return false;
    }
    
  • -3

    要小心这一点 . 我有同样的问题,Firefox或资源管理器都没有滚动

    $('body').animate({scrollTop:pos_},1500,function(){do X});
    

    所以我像大卫一样说道

    $('body, html').animate({scrollTop:pos_},1500,function(){do X});
    

    伟大的工作,但新的问题,因为有两个元素,身体和HTML,功能执行两次,这是,做X运行两次 .

    我只尝试使用'html',Firefox和Explorer工作,但现在Chrome不支持此功能 .

    因此需要Chrome的主体,以及Firefox和Explorer的html . 这是一个jQuery错误吗?不知道 .

    只要注意你的功能,因为它会运行两次 .

  • 0

    我建议不要依赖 bodyhtml 作为更便携的解决方案 . 只需在主体中添加一个div,其目的是包含滚动元素并设置样式以启用全尺寸滚动:

    #my-scroll {
      position: absolute;
      width: 100%;
      height: 100%;
      overflow: auto;
    }
    

    (假设 display:block;top:0;left:0; 是与您的目标匹配的默认值),然后使用 $('#my-scroll') 为您的动画 .

  • 19

    这是实打实的 . 它完美适用于Chrome和Firefox . 甚至有些无知的人投票让我失望 . 此代码在所有浏览器上都可以完美地运行 . 您只需要添加一个链接并将要滚动的元素的ID放在href中,它可以在不指定任何内容的情况下工作 . 纯可重用且可靠的代码 .

    $(document).ready(function() {
      function filterPath(string) {
        return string
        .replace(/^\//,'')
        .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
        .replace(/\/$/,'');
      }
      var locationPath = filterPath(location.pathname);
      var scrollElem = scrollableElement('html', 'body');
    
      $('a[href*=#]').each(function() {
        var thisPath = filterPath(this.pathname) || locationPath;
        if (locationPath == thisPath
        && (location.hostname == this.hostname || !this.hostname)
        && this.hash.replace(/#/,'') ) {
          var $target = $(this.hash), target = this.hash;
          if (target) {
            var targetOffset = $target.offset().top;
            $(this).click(function(event) {
              event.preventDefault();
              $(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
                location.hash = target;
              });
            });
          }
        }
      });
    
      // use the first element that is "scrollable"
      function scrollableElement(els) {
        for (var i = 0, argLength = arguments.length; i <argLength; i++) {
          var el = arguments[i],
              $scrollElement = $(el);
          if ($scrollElement.scrollTop()> 0) {
            return el;
          } else {
            $scrollElement.scrollTop(1);
            var isScrollable = $scrollElement.scrollTop()> 0;
            $scrollElement.scrollTop(0);
            if (isScrollable) {
              return el;
            }
          }
        }
        return [];
      }
    });
    
  • -5

    我刚刚遇到了同样的问题,我通过这样做解决了这个问题:

    $ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top}, 'fast'});
    

    和你!它适用于所有浏览器 .

    如果定位不正确,您可以通过这样做从offset() . top中减去一个值

    $ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top-desired_value}, 'fast'});
    

相关问题