7cc@はてなブログ

JavaScriptとかとか

$(_window).animate

$(html, body).animateの代わり
$(window).animate じゃなく $(_window).animateなんです...

方法

window.scrollByで実際にスクロールして、html, bodyそれぞれのscrollLeft/Topどちらが変化したか調べるだけ。楽で、互換性(ブラウザ、描画モードの違い)も確保。
一度分かったらスクロールせずに関数のプロパティにして返すようにする。

IE9+ならObject.defineProperty + get でgetterにするのも良いと思う。
その都度実行すれば済むので見た目以外恩恵は無いと思う。

絶対にそのページがスクロール可能だと確信がある時はgetterにせずにただの変数として代入もできるが実際には、(1)要素の追加 (2)ブラウザサイズ変更 などでスクロール不可だったページが可能になることもあり得るので望ましくない。

コード

共通部分

// どちらがスクロールするか調べる関数
function getScrollasWindow() {
  if (getScrollasWindow.ele) return getScrollasWindow.ele
  var html = document.documentElement, body = document.body
  if (html.scrollLeft || html.scrollTop) return getScrollasWindow.ele = html
  if (body.scrollLeft || body.scrollTop) return getScrollasWindow.ele = body
  scrollBy(1, 1)
  return getScrollasWindow.ele = (html.scrollLeft || html.scrollTop) ?
    (scrollBy(-1, -1), html) : (body.scrollLeft || body.scrollTop) ?
    (scrollBy(-1, -1), body) : false
}

以下は上のコードに続く

IE9+

// _windowをgetterにする
var scrollObj = {}
Object.defineProperty(scrollObj, "scroll", {
  get: getScrollasWindow
})

var _window = scrollObj.scroll

// usage
$(_window).animate({
  scrollTop: 1000
});

IE8- (9+でもOK)

// usage 変わるのはここだけ
$(getScrollasWindow()).animate({
  scrollTop: 1000
});

間違えて消してしまったので再度公開