会社用の小さなHTML5 Webアプリケーションを作成しました。
このアプリケーションはアイテムのリストを表示し、すべてが正常に機能します。
このアプリケーションは主にAndroid電話とChromeでブラウザーとして使用されます。また、サイトはホーム画面に保存されるため、Android全体をアプリとして管理します(私が推測するWebViewを使用して)。
クロム ベータ版(およびAndroid System WebViewも考えます) 「プルダウンして更新」機能を導入しました( 例についてはこのリンクを参照 )。
これは便利な機能ですが、リストをナビゲートしているときにユーザーが更新を簡単にトリガーでき、アプリ全体がリロードされるため、何らかのメタタグ(またはJavaScriptのもの)で無効にできるかどうか疑問に思いました。
また、これはアプリケーションが必要としない機能です。
この機能はChromeベータ版でのみ利用可能であることは知っていますが、安定版アプリにも登場しているという感覚があります。
ありがとうございました!
編集:Chrome Betaをアンインストールし、ホーム画面に固定されたリンクが安定したChromeで開きます。そのため、固定リンクはChromeで始まり、Webビューではありません。
編集:今日(2015-03-19)リフレッシュプルダウンが安定したクロムになりました。
編集:@Evynの回答から このリンク をたどると、このjavascript/jqueryコードが機能します。
var lastTouchY = 0;
var preventPullToRefresh = false;
$('body').on('touchstart', function (e) {
if (e.originalEvent.touches.length != 1) { return; }
lastTouchY = e.originalEvent.touches[0].clientY;
preventPullToRefresh = window.pageYOffset == 0;
});
$('body').on('touchmove', function (e) {
var touchY = e.originalEvent.touches[0].clientY;
var touchYDelta = touchY - lastTouchY;
lastTouchY = touchY;
if (preventPullToRefresh) {
// To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
preventPullToRefresh = false;
if (touchYDelta > 0) {
e.preventDefault();
return;
}
}
});
@bcintegrityが指摘したように、将来的にはサイトマニフェストソリューション(および/またはメタタグ)を期待しています。
さらに、上記のコードに関する提案を歓迎します。
プルツーリフレッシュエフェクトのデフォルトアクションは、次のいずれかを実行することで効果的に防止できます。
preventDefault
(最も破壊的なものから破壊的なものの順に):touch-action: none
」をタッチターゲット要素に適用し、必要に応じて、タッチシーケンスのデフォルトアクション(プルトゥリフレッシュを含む)を無効にします。overflow-y: hidden
」を適用し、必要に応じてスクロール可能なコンテンツにdivを使用します。chrome://flags/#disable-pull-to-refresh-effect
を介してローカルでエフェクトを無効にします。Chrome 63(2017年12月5日リリース)は、これを正確に支援するcssプロパティを追加しました。 Googleのこのガイド を読んで、それをどのように処理できるかをよく理解してください。
TL:DRはここにあります
CSSのoverscroll-behaviorプロパティを使用すると、開発者はコンテンツの最上部/最下部に到達したときにブラウザーのデフォルトのオーバーフロースクロール動作をオーバーライドできます。ユースケースには、モバイルでのプルトゥリフレッシュ機能の無効化、オーバースクロールグローとラバーバンディング効果の削除、モーダル/オーバーレイの下にあるページコンテンツのスクロール防止などがあります。
動作させるには、CSSに以下を追加するだけです。
body {
overscroll-behavior: contain;
}
また、現時点ではChrome、Edge、Firefoxで サポート のみですが、Safariはサービスワーカーと将来のPWAが完全に搭載されているように見えるので、すぐに追加されると確信しています。
現時点では、この機能を無効にできるのは chrome:// flags /#disable-pull-to-refresh-effect -デバイスから直接開くだけです。
touchmove
イベントをキャッチしようとすることもできますが、許容可能な結果を達成する可能性は非常にわずかです。
MooToolsを使用し、ターゲット要素の更新を無効にするクラスを作成しましたが、その核心は(ネイティブJS)です。
var target = window; // this can be any scrollable element
var last_y = 0;
target.addEventListener('touchmove', function(e){
var scrolly = target.pageYOffset || target.scrollTop || 0;
var direction = e.changedTouches[0].pageY > last_y ? 1 : -1;
if(direction>0 && scrolly===0){
e.preventDefault();
}
last_y = e.changedTouches[0].pageY;
});
ここで行うことは、タッチムーブのy方向を見つけることだけです。画面を下に移動し、ターゲットスクロールが0の場合、イベントを停止します。したがって、更新はありません。
これは、すべての「移動」で発砲することを意味しますが、これは高価になる可能性がありますが、私がこれまでに見つけた最良の解決策です...
何時間も試してみた後、このソリューションは私のために機能します
$("html").css({
"touch-action": "pan-down"
});
私はこのAngularJSディレクティブでそれを正常に無効にしました:
//Prevents "pull to reload" behaviour in Chrome. Assign to child scrollable elements.
angular.module('hereApp.directive').directive('noPullToReload', function() {
'use strict';
return {
link: function(scope, element) {
var initialY = null,
previousY = null,
bindScrollEvent = function(e){
previousY = initialY = e.touches[0].clientY;
// Pull to reload won't be activated if the element is not initially at scrollTop === 0
if(element[0].scrollTop <= 0){
element.on("touchmove", blockScroll);
}
},
blockScroll = function(e){
if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
e.preventDefault();
}
else if(initialY >= e.touches[0].clientY){ //Scrolling down
//As soon as you scroll down, there is no risk of pulling to reload
element.off("touchmove", blockScroll);
}
previousY = e.touches[0].clientY;
},
unbindScrollEvent = function(e){
element.off("touchmove", blockScroll);
};
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);
}
};
});
リフレッシュするためのプルはトリガーされる可能性がないため、ユーザーがスクロールダウンするとすぐに視聴を停止しても安全です。
同様に、scrolltop > 0
の場合、イベントはトリガーされません。私の実装では、scrollTop <= 0
の場合にのみ、touchstartでtouchmoveイベントをバインドします。ユーザーが下にスクロールするとすぐにバインドを解除します(initialY >= e.touches[0].clientY
)。ユーザーが上にスクロールすると(previousY < e.touches[0].clientY
)、preventDefault()
を呼び出します。
これにより、スクロールイベントを不必要に監視する必要がなくなり、オーバースクロールがブロックされます。
JQueryを使用している場合、これは未テストと同等です。 element
はjQuery要素です。
var initialY = null,
previousY = null,
bindScrollEvent = function(e){
previousY = initialY = e.touches[0].clientY;
// Pull to reload won't be activated if the element is not initially at scrollTop === 0
if(element[0].scrollTop <= 0){
element.on("touchmove", blockScroll);
}
},
blockScroll = function(e){
if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
e.preventDefault();
}
else if(initialY >= e.touches[0].clientY){ //Scrolling down
//As soon as you scroll down, there is no risk of pulling to reload
element.off("touchmove");
}
previousY = e.touches[0].clientY;
},
unbindScrollEvent = function(e){
element.off("touchmove");
};
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);
当然、純粋なJSでも同じことが実現できます。
標準のJavaScriptを使用して実装しました。シンプルで簡単に実装できます。貼り付けるだけで問題なく動作します。
<script type="text/javascript"> //<![CDATA[
window.addEventListener('load', function() {
var maybePreventPullToRefresh = false;
var lastTouchY = 0;
var touchstartHandler = function(e) {
if (e.touches.length != 1) return;
lastTouchY = e.touches[0].clientY;
// Pull-to-refresh will only trigger if the scroll begins when the
// document's Y offset is zero.
maybePreventPullToRefresh =
window.pageYOffset == 0;
}
var touchmoveHandler = function(e) {
var touchY = e.touches[0].clientY;
var touchYDelta = touchY - lastTouchY;
lastTouchY = touchY;
if (maybePreventPullToRefresh) {
// To suppress pull-to-refresh it is sufficient to preventDefault the
// first overscrolling touchmove.
maybePreventPullToRefresh = false;
if (touchYDelta > 0) {
e.preventDefault();
return;
}
}
}
document.addEventListener('touchstart', touchstartHandler, false);
document.addEventListener('touchmove', touchmoveHandler, false); });
//]]> </script>
純粋なCSSの最適なソリューション:
body {
width: 100%;
height: 100%;
display: block;
position: absolute;
top: -1px;
z-index: 1;
margin: 0;
padding: 0;
overflow-y: hidden;
}
#pseudobody {
width:100%;
height: 100%;
position: absolute;
top:0;
z-index: 2;
margin: 0;
padding:0;
overflow-y: auto;
}
このデモを参照してください: https://jsbin.com/pokusideha/quiet
あなたの設定を見つけます 体 CSS オーバーフローy:非表示 最も簡単な方法です。スクロールアプリケーションページが必要な場合は、スクロール機能を備えたdivコンテナを使用できます。
数週間後、Chrome更新アクションを無効にするために使用したjavascript関数が機能しなくなることがわかりました。私はそれを解決するためにこれを作りました:
$(window).scroll(function() {
if ($(document).scrollTop() >= 1) {
$("html").css({
"touch-action": "auto"}
);
} else {
$("html").css({
"touch-action": "pan-down"
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
Overflow-yは継承されないため、すべてのブロック要素に設定する必要があることに注意してください。
次の方法でjQueryを使用してこれを行うことができます。
$(document.body).css('overflow-y', 'hidden');
$('*').filter(function(index) {
return $(this).css('display') == 'block';
}).css('overflow-y', 'hidden');
純粋なjsソリューション。
// Prevent pull refresh chrome
var lastTouchY = 0;
var preventPullToRefresh = false;
window.document.body.addEventListener("touchstart", function(e){
if (e.touches.length != 1) { return; }
lastTouchY = e.touches[0].clientY;
preventPullToRefresh = window.pageYOffset == 0;
}, false);
window.document.body.addEventListener("touchmove", function(e){
var touchY = e.touches[0].clientY;
var touchYDelta = touchY - lastTouchY;
lastTouchY = touchY;
if (preventPullToRefresh) {
// To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
preventPullToRefresh = false;
if (touchYDelta > 0) {
e.preventDefault();
return;
}
}
}, false);
私がしたことは、touchstart
およびtouchend
/touchcancel
イベントに以下を追加することでした:
scrollTo(0, 1)
chromeがscrollY位置にない場合はスクロールしないので、0
はchromeがプルしてリフレッシュするのを防ぎます。
それでも機能しない場合は、ページが読み込まれたときにもそれを試してください。
私はこれでプルダウンからリフレッシュの問題を解決しました:
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}