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

F.Ko-Jiの「一秒後は未来」 > プログラミング (全 155 件)

サブカテゴリー: Chef Greasemonkey Javascript Linux MongoDB MySQL Node.js PHP Swift iPhoneアプリ開発 jQuery

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年09月14日 17:54

リアル脱出ゲーム『アイドルは100万回死ぬ』と論理的思考について

2016年05月20日 15:52

GitHubのContributionsグラフにプライベートの活動を表示できるようになってた

2016年04月27日 04:31

プログラミングを学ぶ際に「何が自分にとって楽しいか?」を考える

2016年03月17日 21:20

Chrome DevTools のデバイスモードでスマートフォンを選択するには?

2016年02月10日 20:47

Atom 上でドットインストールを再生できるパッケージ「Dotinstall Pane」を作りました

2016年01月16日 23:23

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

2015年09月28日 18:16

Google Apps Scriptを外部から実行できるGoogle Apps Script Execution APIを試してみた

2015年09月15日 23:45

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

2015年08月31日 17:55

Macでmodern.ieのzipファイルがうまく解凍できない場合

2015年07月28日 18:59

Selenium WebDriver と Chrome で StaleElementReferenceError が頻発するようになったので対処した

2015年05月22日 01:37

自分ルールその1: 眠いときにプログラミング作業をしない

2015年02月26日 06:27

heroku pg:pull 実行時に「FATAL: Ident authentication failed for user」というエラー

2015年02月15日 00:56

VimeoのAPIを扱う際にはAcceptヘッダでバージョンを指定しておくとよい

2015年02月08日 14:24

nginxのX-Accel-Redirectを試してみる

2015年01月23日 23:56

PHPからDropBox APIを使ってみた

2015年01月19日 23:50

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

2015年01月11日 23:58

「詳解Swift」を購入しました

2015年01月06日 23:37

学校の授業が生み出した苦手意識

2015年01月05日 22:43

PHPでHTTPリクエストを扱える「Guzzle」ライブラリ