iscroll-probe.jsでiOS7以下でもスクロールイベントを取得
- 書いた人:
- tanippa!
- カテゴリ:
- javascript jQuery
- 10,245 views
iOS8では改善されましたが、iOS7以下でスクロールイベントを取得したいという状況も結構発生するかと思います。そこで今回はiscroll-probe.jsを使用して、スクロールイベントを擬似的に取得する方法をご紹介したいと思います。
以前はiOSではスクロール中はスクロールイベントが発生せず、スクロール終了時にイベントが発火されるという仕様でしたが、それがiOS8になり改善され、スクロール中にもイベントが発火されるようになりました。
ただ、まだiOS7使用者が無視できない割合で居ることから、案件の対応OSにiOS7が入ることも多く、iOS7以下でスクロールイベントを取得したいという状況も結構発生するかと思います。
そこで、今回はiscroll-probe.jsを使用して、スクロールイベントを擬似的に取得する方法をご紹介したいと思います。
iScroll5ライブラリの取得
iScroll 5, smooth scrolling for the web
上の公式サイトの「DOWNLOAD」リンクからライブラリ一式をダウンロードしてください。
中に多くのファイルが入っていますが、今回使用するのは「build」ディレクトリ内の「iscroll-probe.js」のみですので、「iscroll-probe.js」を適宜好きな場所へ配置してください。
ライブラリの読み込み
headタグ内で、iscroll-probe.jsを読み込んでください。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="./common/js/lib/iscroll-probe.js"></script>
今回は一部jQueryを使用するためjQueryも読み込んでいます。使用しない場合は読み込む必要はありません。
HTML
iscrollでは、コンテンツ全体を2つのラッパーで囲む必要があります。
今回は以下の様な構造にします。
<body onload="loaded()"> <div id="WholeWrapper"> <div id="WholeInner"> <!-- コンテンツを記述 --> </div> </div> </body>
idやクラスには特に規定は無いので自由に付けて大丈夫です。
bodyタグに記述しているonloadコールバック関数に関しては後述します。
CSS
一番外側のラッパーに対しては下記のようなスタイルを当てる必要があります。
#WholeWrapper { position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; width: 100%; overflow: hidden; }
javascript
<script> var myScroll; function updatePosition () { $(window).trigger('iscroll', {x: this.x, y: this.y}); } // onloadイベント発生時にこの関数を呼び出す function loaded () { myScroll = new IScroll('#WholeWrapper', { deceleration: 0.004, // スクロール時の慣性の強さ probeType: 3, mouseWheel: true }); myScroll.on('scroll', updatePosition); myScroll.on('scrollEnd', updatePosition); } document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); $(function(){ $(window).on('iscroll', function(e, pos){ console.log(pos); // スクロール中にもスクロール位置が取得可能 }); }); </script>
IScroll初期化時に指定している「deceleration」は慣性の強さで、この値が大きいほどスクロールがすぐ停止するようになります。初期値は「0.0006」なのですが、この値だとiOS Safariの慣性と比較して慣性が異常に強く、スクロールしすぎてしまうので適宜値を調整しましょう。
スクロール系関数
iScrollには様々な関数が用意されているのですが、その中でも一番使用頻度が多いと思われるスクロール系関数を紹介したいと思います。
scrollTo(x, y, time, easing)
(x, y)地点へtimeミリ秒かけてスクロールします。
myScroll.scrollTo(0, -1000, 500, IScroll.utils.ease.elastic);
easingはスクロールの際の加減速の仕方のバリエーションで、quadratic,circular,back,bounce,elasticの5パターン存在しています。
scrollToElement(el, time, offsetX, offsetY, easing)
要素elまでtimeミリ秒かけてスクロールします。その際、止まる位置はoffsetの指定によってずらすことが可能です。easingはscrollToと同じです。
myScroll.scrollToElement(document.getElementById('TargetId'), 1000);
iScrollは構造上アンカーリンクが効かなくなってしまうので、代わりにこのscrollToElementを使用して機能を実装する必要があります。
他にも、現在のスクロール位置から相対的に移動するscrollByが存在しています。
以上
これで一応iOS7以下でもスクロールイベントを取得出来るようにはなるのですが、前述のとおり、iScrollは内側のラッパーをtranslateにより移動させることにより擬似的にスクロールイベントを再現している仕組みのため、アンカーリンクが正常に機能しません。他にも正常に動作しなくなる、または通常より実装に工数が大幅にかかってしまう機能がある可能性が高いので、使用にはかなり気をつける必要があります。
また、iOS7では動作することを確認しましたが、iOS7未満やAndroidでは動作未確認ですのでご注意ください。
以上、たにっぱでした〜