慣性スクロールをJQueryでシュミレート


まだ慣性スクロールにCSSが使えなかった時代、ページの一部を慣性スクロールさせるにはJQuery(JavaScript)を使っていました。

今では、CSSだけで簡単に慣性スクロールができるので、JQueryでの慣性スクロールは、あまり需要がないかもしれません。しかし、スライドショーの自作なんかには応用できると思うし、いつか誰かの役に立つかもしれないのでここに記録しておきます。

ちなみに、比較しやすいように、スマートフォンやタブレットなどのタッチデバイスじゃないと動かないようにしているのでご注意ください。

まずはデモで動きを確認

ページの一部分だけを慣性スクロールさせたかったら、CSS3を使えば簡単に実現できます。たった2行でOKです。
overflow: scroll;
-webkit-overflow-scrolling: touch;

CSS3の -webkit-overflow-scrolling を使うと、こんな感じで動きます。スマホでグリグリしてみてください。

  1. スクロール開始
  2. テスト
  3. CSS3でスクロール
  4. テスト
  5. CSS3でスクロール
  6. テスト
  7. CSS3でスクロール
  8. テスト
  9. CSS3でスクロール
  10. テスト
  11. CSS3でスクロール
  12. テスト
  13. CSS3でスクロール
  14. テスト
  15. CSS3でスクロール
  16. テスト
  17. CSS3でスクロール
  18. テスト
  19. CSS3でスクロール
  20. テスト
  21. CSS3でスクロール
  22. テスト
  23. CSS3でスクロール
  24. テスト
  25. CSS3でスクロール
  26. テスト
  27. CSS3でスクロール
  28. テスト
  29. JQueryでスクロール
  30. スクロール終わり

 

次に、JQueryで自作した慣性スクロールです。(パソコンでは動きません。)

  1. スクロール開始
  2. テスト
  3. JQueryでスクロール
  4. テスト
  5. JQueryでスクロール
  6. テスト
  7. JQueryでスクロール
  8. テスト
  9. JQueryでスクロール
  10. テスト
  11. JQueryでスクロール
  12. テスト
  13. JQueryでスクロール
  14. テスト
  15. JQueryでスクロール
  16. テスト
  17. JQueryでスクロール
  18. テスト
  19. JQueryでスクロール
  20. テスト
  21. JQueryでスクロール
  22. テスト
  23. JQueryでスクロール
  24. テスト
  25. JQueryでスクロール
  26. テスト
  27. JQueryでスクロール
  28. テスト
  29. JQueryでスクロール
  30. スクロール終わり

 

最初のCSSの方は、使っているデバイスによって動きが異なります。また、JQueryの方が動きがゆっくりですがスピード調整は可能です。このように微調整できるのは、自作JQueryの方が、CSSより優れている点でだと思います。

実際のコードを公開

それでは、実際にJQueryのコードを見て見ましょう。

/*****************************************************************************************
    目次のスクロール処理 
*****************************************************************************************/

//【重要】以下の二つの変数にスクロールさせたい要素を格納する。
var $target_wrap = $("#target-wrapper");
var $target = $("#target");

$(function () {
	
	var flick_flg = true;	//フラグ
	var spd = 400;			//フリックスピード【スピードを変更したいならここの数値を変える】
	var distance = 0;		//移動距離を指定するのに使う
	var index = 1;
	
	/****** スライド関数ここから ******/
	var slide = {

		// スライド(進む)	
		next: function (index, spd, flick_flg) {
			distance = distance + index;
			slide.scroll(distance, spd, flick_flg);
		},
		// スライド(戻る)
		prev: function (index, spd, flick_flg) {
			distance = distance - index;
			slide.scroll(distance, spd, flick_flg);
		},
		// 上端での跳ね返り
		topNext: function (index, spd, flick_flg) {
			distance = distance + index;
			slide.scroll(distance, spd, flick_flg);
		},
		// 下端での跳ね返り
		bottomPrev: function (index, spd, flick_flg) {
			distance = distance - index;
			slide.scroll(distance, spd, flick_flg);
		},
		// 移動距離分スクロール
		scroll : function (d, spd, flick_flg) {
			
			var move = -d;
			var env = "translate3d(0," + move + "px,0)";
				
			if (flick_flg) {
				/**** フリック時はwebkit-transformプロパティを設定し、滑らかなアニメーションにする ****/
				transit_property = "-webkit-transform " + spd + "ms cubic-bezier(0,0,0.25,1)";
			} else{
				transit_property = "none";
			}

			$target.css({
					"-webkit-transform":env,
					"-webkit-transition":transit_property
				}).on("webkitTransitionEnd", function(){
				//ここで移動後の終了イベントが取れる
				});
		}
}

$(window).load(function() {

	var pageY;	//リアルタイムのY座標
	var startPageY;	//スタート時のY座標の位置
	var startTime;	//スタート時の時間
	var move_time = 0;

	/**** タッチの開始時のイベント ****/
	$target_wrap.on("touchstart", function(e){
		event.preventDefault();		// Aタグなどの反応を止める
    	pageY = event.changedTouches[0].pageY;	// タッチされている画面位置のY座標
		startPageY = pageY;
    	startTime = +new Date();
	});
	
	/**** タッチしたまま動かしたときのイベント ****/
	$target_wrap.on("touchmove", function(e){
  		
    	var moveY = event.changedTouches[0].pageY;	// タッチされている画面位置のY座標
    	var absY = Math.abs(pageY - moveY);		// 移動距離の絶対値を返す
	
    	myTop = $target.position().top;
    	myTop_abs = Math.abs(myTop);	
		target_height = $target.height() ;
		window_height = $(window).height();
		myScroll_abs = Math.abs(target_height - window_height);

		/**** スワイプ処理 ****/ 
    	if (pageY > moveY && myTop_abs < myScroll_abs){
      		slide.next(absY *0.9);
    	}
    	else if (pageY < moveY && myTop < 0){
        	slide.prev(absY *0.9);
    	}
    	else if (pageY < moveY && myTop >= 0){
        	slide.bottomPrev(absY *0.33);
    	}
    	else if (pageY > moveY && myTop_abs > myScroll_abs ){
      		slide.topNext(absY *0.5);
    	}
    	pageY = moveY;
	});

	/**** タッチ状態から離れたときのイベント ****/
	$target_wrap.on("touchend", function(e){
		/* 終了処理が必要ならここに書く */
		/* このイベントは、位置を取得できないので注意 */
	
    	var diff = startPageY - pageY;
    	var absY = Math.abs(diff);
    	var mv = 80;			//フリック移動距離
        var now = +new Date();		//現在時間
    	var diffTime = now - startTime;	//touchstartからの経過時間
    	
    	//【重要】下端での跳ね返り距離は、ここの数値を変更して調整できます。
        var myBottom = myTop_abs - myScroll_abs +200;	

  /************* フリック処理(フリックダウン) ************/
 //フリックダウンの基本的なスライド処理
 if (diffTime < 400 && diff < -100 && myTop < -35){ 
 slide.prev(mv, spd, true); 
 }
 //短いフリックに対応させる
 else if (diffTime < 400 && -100 <diff && diff <0 && myTop < -45 ){
 slide.prev(mv-30, spd+500, true);
 }
 
 /************* フリック処理(フリックアップ) ************/
 //フリックアップの基本的なスライド処理
 else if (diffTime < 400 && 100 < diff && myTop_abs <= myScroll_abs -70){
 slide.next(mv, spd, true);
 }
 //短いフリックに対応させる
 else if (diffTime < 400 && 0 < diff && diff < 100 && myTop_abs <= myScroll_abs){
 slide.next(mv-30, spd+500, true);
 }
 
 /************* スクロール上限と下限での跳ね返り処理 ************/
 //上端での跳ね返り処理
 else if (myTop > 0 && diff < 0) {
 slide.topNext(myTop, spd, true); 
 }
 //下端での跳ね返り処理
 else if (myTop_abs > myScroll_abs && diff > 0 ){
 slide.bottomPrev(myBottom, spd, true);
 //alert(myScroll_abs);
 }
    
    move_time = 0;
    });

});
});//目次のスクロール処理【END】


 

使い方は簡単で、6行目と7行目に手を加えてあげるだけです。

慣性スクロールさせたい要素のセレクタを、7行目の $(“#target”); から変更します。例えば、#sidebar を慣性スクロールさせたければ、 $(“#sidebar”); と変更します。

次に、慣性スクロールさせたい要素を、新たな要素(セレクタ)を作って囲みます。6行目のvar $target_wrap = $(“#target-wrapper”); の部分ですね。

そして、この $(“#target-wrapper”); に自身で作ったセレクタを代入すればOKです。

コードの説明は、コードの中にコメントで書き込んでいるので、参考になさってくだい。

以上、「慣性スクロールをJQueryでシュミレート」でした。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です