この機能は正常に動作します。目的のコンテナのオフセットまで本体をスクロールします
function scrolear(destino){
var stop = $(destino).offset().top;
var delay = 1000;
$('body').animate({scrollTop: stop}, delay);
return false;
}
しかし、Firefoxではそうではありません。どうして?
-編集-
受け入れられた答えでデダブルトリガーを処理するには、アニメーションの前に要素を停止することをお勧めします。
$('body,html').stop(true,true).animate({scrollTop: stop}, delay);
Firefoxは、異なる動作をするよう特別にスタイル設定されていない限り、html
レベルでオーバーフローを配置します。
Firefoxで動作させるには、以下を使用します
$('body,html').animate( ... );
CSSソリューションは、次のスタイルを設定することです。
html { overflow: hidden; height: 100%; }
body { overflow: auto; height: 100%; }
JSソリューションは最も侵襲性が低いと思います。
更新
以下の説明の多くは、2つの要素のscrollTop
をアニメートすると、コールバックが2回呼び出されるという事実に焦点を当てています。ブラウザー検出機能が提案され、その後廃止されました。一部の機能は、おそらくかなり手に負えないものです。
コールバックがべき等であり、多くの計算能力を必要としない場合、2回呼び出すことは完全に問題ではないかもしれません。コールバックの複数の呼び出しが本当に問題であり、機能の検出を回避したい場合、コールバックがコールバック内から1回だけ実行されるように強制する方が簡単です。
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');
}));
機能を検出し、サポートされている単一のオブジェクトをアニメーション化するのはいいことですが、1行のソリューションはありません。それまでの間、promiseを使用して実行ごとに1つのコールバックを実行する方法を次に示します。
$('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();
ここで、ページスクロールアニメーションのセレクターとして定義した変数を使用し、通常の構文を使用します。
$(scrollTopElement).animate({ scrollTop: 100 }, 500, function() {
// normal callback
});
私のコードが機能しない理由を解明しようと長い間費やしました-
$('body,html').animate({scrollTop: 50}, 500);
問題は私のCSSにありました-
body { height: 100%};
代わりにauto
に設定しました(最初に100%
に設定された理由について心配していました)。それは私のためにそれを修正しました。
プラグインを使用して問題を回避したい場合があります。具体的には、 my plugin :)
真剣に、基本的な問題は長い間対処されてきましたが(異なるブラウザはウィンドウのスクロールに異なる要素を使用します)、後を追う可能性のある重要な問題がかなりあります:
body
とhtml
の両方をアニメーション化する 問題がある 、私は明らかに偏っていますが、 jQuery.scrollable は実際にこれらの問題に対処するための良い選択です。 (実際、それらをすべて処理する他のプラグインは知りません。)
さらに、 このGistのgetScrollTargetPosition()
関数 を使用して、防弾方式でターゲット位置(スクロールする位置)を計算できます。
すべてがあなたを残すだろう
function scrolear ( destino ) {
var $window = $( window ),
targetPosition = getScrollTargetPosition ( $( destino ), $window );
$window.scrollTo( targetPosition, { duration: 1000 } );
return false;
}
これに注意してください。 FirefoxとExplorerのどちらでもスクロールできないという同じ問題がありました
$('body').animate({scrollTop:pos_},1500,function(){do X});
だからデビッドが言ったように使った
$('body, html').animate({scrollTop:pos_},1500,function(){do X});
うまくいきましたが、新しい問題です。bodyとhtmlの2つの要素があるため、関数が2回実行されます。つまり、Xは2回実行されます。
'html'のみで試行し、FirefoxとExplorerは動作しますが、現在Chromeはこれをサポートしていません。
そのため、Chromeにはbody、FirefoxとExplorerにはhtmlが必要でした。 jQueryのバグですか?わからない。
関数は2回実行されるため、注意してください。
notよりポータブルなソリューションとしてbody
またはhtml
に依存することをお勧めします。スクロール要素を含むことを目的としたdivを本体に追加し、フルサイズのスクロールを有効にするようにスタイルを設定します。
#my-scroll {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}
(display:block;
とtop:0;left:0;
が目標に一致するデフォルトであると仮定して)、アニメーションに$('#my-scroll')
を使用します。
私は最近同じ問題に遭遇し、これを行うことでそれを解決しました:
$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top}, 'fast'});
そしてyoupi !!!すべてのブラウザで動作します。
位置が正しくない場合は、これを行うことでオフセット().topから値を引くことができます
$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top-desired_value}, 'fast'});
これが本当の取引です。 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 [];
}
});