スクロールイベントの開始 / 終了 / 方向を判定する jQuery プラグインを書いてみた
バージョンアップしました。詳細は以下記事をご覧ください。
[Ex Scroll] スクロールイベントの開始/終了、方向を判別できる jQuery プラグイン - Cyokodog需要なさそうですが、備忘録ということで。
只今、以前作成した exFixed.js という jQuery プラグインの機能拡張を行っており、その中で、
- スクロールイベントの開始、終了時にのみ処理を行う
- その際、スクロールイベントのスクロール方向に応じて処理を変える
という実装が必要になりました。
jQuery におけるスクロールイベントの割当は下記のような記述になりますが、このままではイベントの開始,終了,スクロール方向は判別できません。
$( element ).scroll( function( evt ){ //スクロールイベント内処理 });
以下の実装で判別できないか考えてみました。
スクロール方向の判別
- スクロールイベント開始前のスクロール位置 ( scrollTop , scrollLeft ) を事前に保持しておく
- スクロールイベント中のスクロール位置と保持しておいた値を比較し、値のずれの有無でスクロール方向を判別する
スクロールイベントの開始、終了の判別
- 状態フラグを設けこれを参照することで開始 / 終了状態を判別する
- スクロールイベントが開始されたら、「開始フラグ(1)」を立てる
- スクロールイベントは連続して起こるので、後続するスクロールで「開始フラグ(1)」が立ってた場合は、「スクロール中フラグ(2)」を立てる
- スクロールイベント内では setTimeout を使用し「終了フラグ(0)」セットルーチンを毎回起動する。但し、前回コール分の setTimeout が終了してない場合は、clearTimeout でこれをクリアする
jQuery プラグインで実装
汎用的に使用できるようプラグイン化してみました。
ソース
(function($j){ $j.ex = $j.ex || {}; $j.ex.scrollEvent = function( target , config ){ var o = this; if( typeof config == 'function') config = { callback : config } var c = o.config = $j.extend({},$j.ex.scrollEvent.defaults,config,{ target : target }); c.status = 0; c.scroll = o.getPos(); c.target.scroll(function( evt ){ if (o.isMove()) { c.status = (c.status == 0 ? 1 : (c.status == 1 ? 2 : c.status) ); c.callback( evt , c ); } if(c.tm) clearTimeout(c.tm); c.tm = setTimeout(function(){ o.isMove(); c.status = 0; c.callback( evt , c ); },c.delay); }); } $j.extend($j.ex.scrollEvent.prototype,{ isMove : function(){ var o = this, c = o.config; var pos = o.getPos(); var scrollY = (pos.top != c.scroll.top); var scrollX = (pos.left != c.scroll.left); if(scrollY || scrollX){ c.scrollY = scrollY; c.scrollX = scrollX; c.prevScroll = c.scroll; c.scroll = pos; return true; } return false; }, getPos : function(){ var o = this, c = o.config; return { top : c.target.scrollTop(), left : c.target.scrollLeft() } } }); $j.ex.scrollEvent.defaults = { delay : 100 } $j.fn.exScrollEvent = function( config ){ new $j.ex.scrollEvent(this , config); return this; }; })(jQuery);
使い方
jquery.js、jquery.exscrollevent.js の順で読み込ませます。
<script src="jquery.js"></script> <script src="jquery.exscrollevent.js"></script>
コールバック関数の第 2 引数にパラメータオブジェクトが渡されますので、これを参照し状態を判別します。
jQuery(function($){ var logbox = $('#logbox'); var target = $('#container'); target.exScrollEvent(function(evt , param){ var txt=''; //X方向にスクロール? if(param.scrollX){ txt += 'X '; } //Y方向にスクロール? if(param.scrollY){ txt += 'Y '; } //スクロール開始 if(param.status == 1){ txt += '<span style="color:pink">scroll start</span>'; } //スクロール終了 if(param.status == 0){ txt += '<span style="color:pink">scroll end</span>'; } //スクロール中 if(param.status == 2){ txt += 'scroll now'; } //スクロール位置 txt += ' ( top:'+param.scroll.top+' , left:'+param.scroll.left+' )'; logbox.html(txt+'<br/>'+logbox.html()) }) $('#clear').click(function(){ logbox.html(''); }) });
その他のパラメータ
- prevScroll
サンプルでは scroll プロパティでスクロールイベント時のスクロール位置を取得してますが、スクロールイベント発生前のスクロール位置は status が 1 (スクロール開始) の時に、prevScroll を参照することで取得できます。
- delay
スクロールイベントの終了判定の間隔を指定できます。
$( element ).exScrollEvent({ delay : 10, // 10ms callback : function( evt , param ){ ... } });
活用方法?
いまいち使いどころが思いつきませんが、jQuery Scroll Follow ( demo ) のような実装が若干簡単になるかな..? ...たいしたメリットじゃないですね。。
jQuery(function($){ $(window).exScrollEvent({ delay : 10, callback : function(evt,param){ if(param.status == 0){ $('#box').queue([]).animate({ top : 100 + param.scroll.top, left : 100 + param.scroll.left }) } } }); });