ネットサービスとかGoogleとか豆知識とか。

F.Ko-Jiの「一秒後は未来」 > プログラミング > Javascript (全 81 件)
2016年10月16日 00:24

jQueryのanimate()によるスクロールなのか手動スクロールなのかをきちんと判別したい

ある要素を自動的にスムーズにスクロールさせたいとき jQueryの animate() を使うことはよくある。例えば 200px だけしゅるしゅるっとスクロールさせたかったら以下のようなコードで可能。

$('#some_el').animate({
    scrollTop: 200
}, 450);

ここでもし、あるスクロールが jQuery の animate() による自動スクロールなのか、ユーザーがマウスでスクロールさせたものなのかを判別したかったとする。調べてみると、jQuery の :animated というセレクタを使うと判別できるらしい。

$('#some_el').on('scroll', function() {
    if ($(this).is(':animated')) {
        console.log('Scroll by animate()');
    } else {
        console.log('Scroll by user');
    }
});

このようにして .is(':animated') が true か false かで判別できる。・・・と思うじゃないですか。ところがコンソールの出力を見てみると、なぜか最後に「Scroll by user」が出力されているのが分かる。

detect-scroll-by-animate-or-manual-01.jpg

つまり animate() の最後の最後で .is(':animated') は false になってしまっているということ。これだと自動スクロールの最後の最後で手動スクロールが実行されたものと判別されてしまう。

ではどうするか?

ここで animate() にコールバック関数を与えてみる。これは animate() の完了時に呼ばれる。

$('#some_el').animate({
    scrollTop: 200
}, 450, function() {
    console.log('Complete animate()');
});

すると、コールバック関数は「Scroll by user」の出力の直前に実行されていることが分かる。

detect-scroll-by-animate-or-manual-02.jpg

ということは、完了時のコールバック関数が呼ばれた直後の scroll イベントは animate() によるものということになるので、例えば変数を 1 個用意して、

var animateFinised = false;

$('#some_el').animate({
    scrollTop: 200
}, 450, function() {
    animateFinised = true;
    console.log('Complete animate()');
});

$('#some_el').on('scroll', function() {
    if (animateFinised) {
        animateFinised = false;
        console.log('Scroll by animate()');
    } else {
        if ($(this).is(':animated')) {
            console.log('Scroll by animate()');
        } else {
            console.log('Scroll by user');
        }
    }
});

とすれば、animate() によるスクロールと手動スクロールとをきちんと判別できるようになる。

detect-scroll-by-animate-or-manual-03.jpg

2016年01月16日 23:23

npmでなぜかホームディレクトリにパッケージがインストールされてしまう現象にハマった

2015年09月15日 23:45

過去に書いた JavaScript を徐々にモジュール化していくことにした

2015年03月08日 10:30

JavaScriptで構築している箇所もHTMLと同等にGoogleにインデックスされつつある

2015年01月19日 23:50

初心者向けJavaScript: ブログ記事の長さに応じてサイドバーの一部を記事下に移動させる

2014年11月07日 20:47

Twitterの絵文字ライブラリ「Twemoji」を簡単に使うための3ステップ

2013年11月24日 17:43

Feedly上で小さいimg要素が消えるのを回避するChrome拡張を作った

2013年07月16日 23:31

AdSenseにページの表示を妨げない非同期型コードが登場

2013年04月05日 09:33

YouTubeのPlayer APIでHTML5プレイヤーかどうかを判別する方法

2012年09月06日 16:05

GoogleドキュメントのフォームからGoogle Apps ScriptでGitHubのIssuesに投稿する

2012年04月15日 14:45

JavaScriptで動的に生成したform要素は明示的にDOMに追加しないとsubmitできない

2012年03月25日 16:20

jQueryの.clone()でdata属性までコピーするには?

2012年01月10日 14:33

JavaScriptやCSSをURLで読み込む際の「http:」は省略できる

2011年08月20日 18:39

FacebookコメントプラグインのアクションもGoogle Analyticsで集計してみよう

2011年07月06日 11:13

new google.maps.infoWindow()は当然undefinedである

2011年04月26日 14:49

enchant.jsゲーム対決 第2弾 いいね!が多いほうが勝ち!

2011年04月21日 14:27

enchant.jsでつくったゲーム対決 @taguchi vs @fkoji いいね!が多いほうが勝ち!

2011年04月20日 16:18

enchant.jsで「クマたたきゲーム」をつくってみたよ

2011年03月09日 01:59

jQueryで動的に作ったradioボタンがIE6とIE7で動作しない場合の対処

2011年02月22日 09:36

JavaScriptの構文エラーやコーディング規約上の問題をチェックしてくれる「JSHint」が便利そう