Анимация scrollTop не работает в firefox



эта функция работает нормально. Он прокручивает тело до смещения нужного контейнера



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


но не в Firefox. Зачем?



- EDIT -



чтобы обработать de double trigger в принятом ответе, я предлагаю остановить элемент перед анимацией:



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

10 ответов:

Firefox помещает переполнение в html уровень, если специально не стилизованы вести себя по-другому.

чтобы заставить его работать в Firefox, используйте

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

пример

решение CSS должно было бы установить следующие стили:

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

Я бы предположил, что решение JS будет наименее инвазивным.


обновление

много обсуждения ниже фокусируется на дело в том, что анимация 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');
}));

обнаружение функций, а затем анимация на одном поддерживаемом объекте было бы неплохо, но нет одного линейного решения. В то же время, вот способ использовать обещание сделать один обратный вызов на выполнение.

$('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
});

Я потратил годы, пытаясь понять, почему мой код не будет работать -

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

проблема была в моем css -

body { height: 100%};

это auto вместо этого (и остался беспокоиться о том, почему он был установлен в 100% в первую очередь). Это исправило все для меня.

вы можете уклониться от проблемы с помощью плагина – более конкретно,плагин :)

серьезно, хотя основная проблема уже давно решена (разные браузеры используют разные элементы для прокрутки окон), есть довольно много нетривиальных проблем, которые могут вас сбить с толку:

Я явно предвзят, но jQuery.прокручивается на самом деле хороший выбор для решения этих вопросов. (На самом деле, я не знаю ни одного другого плагина, который обрабатывает их все.)

В дополнение, вы можете рассчитать целевую позицию-ту, которую вы прокручиваете-пуленепробиваемым способом с the getScrollTargetPosition() функция в этом gist.

все это оставит вас с

function scrolear ( destino ) {
    var $window = $( window ),
        targetPosition = getScrollTargetPosition ( $( destino ), $window );

    $window.scrollTo( targetPosition, { duration: 1000 } );

    return false;
}

остерегайтесь этого. У меня была та же проблема, ни Firefox, ни проводник прокрутки с

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

поэтому я использовал, как сказал Дэвид

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

отлично это сработало, но новая проблема, так как есть два элемента, body и html, функция выполняется дважды, это, do X выполняется два раза.

пробовал только с "html", и Firefox и Explorer работают, но теперь Chrome не поддерживает это.

Так нужен корпус для Chrome, и html для Firefox и Explorer. Это ошибка jQuery? не знаю.

просто остерегайтесь своей функции, так как она будет работать дважды.

Я бы порекомендовал не опираясь на body, ни html как более портативное решение. Просто добавьте div в тело, которое стремится содержать прокручиваемые элементы и стиль его, как для включения полноразмерной прокрутки:

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

(предполагая, что display:block; и top:0;left:0; по умолчанию соответствует вашей цели), затем используйте $('#my-scroll') для вашей анимации.

Это реальная сделка. Он работает на Chrome и Firefox безупречно. Даже печально, что некоторые невежды голосуют против меня. Этот код буквально отлично работает, как и во всех браузерах. Вам нужно только добавить ссылку и поместить идентификатор элемента, который вы хотите прокрутить в 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 [];
  }
});

для меня проблема заключалась в том, что firefox автоматически перескочил на якорь с именем-атрибутом, таким же, как имя хэша, которое я ввел в URL. Хоть я и положил .метод preventDefault (), чтобы предотвратить это. Таким образом, после изменения атрибутов имени firefox не автоматически переходил к якорям, а выполнял анимацию справа.

@Toni Извините, если это не было понятно. Дело в том, что я изменил хэши в URL, как www.someurl.com/#hashname. тогда у меня был например якорь как <a name="hashname" ...></a> к которому jQuery должен прокручиваться автоматически. Но это не так, потому что он прыгнул прямо на якорь с соответствующим атрибутом name В Firefox без какой-либо анимации прокрутки. Как только я изменил атрибут name на что-то отличное от хэш-имени, например на name="hashname-anchor" прокрутка работала.

для меня это было избегание добавления идентификатора в точке анимации:

избежать:

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

подготовка id заранее и делать это вместо этого:

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

исправлено в FF. (CSS дополнения не имеют значения для меня)

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

надеюсь, что это работает.

Comments

    Ничего не найдено.