web-dev-qa-db-ja.com

iOS 10+サファリズームを無効にするビューポート?

私はiPhone 6 plusをiOS 10ベータ版にアップデートしましたが、モバイルサファリではメタタグのuser-scalable=noコードをダブルタップまたはIGNOREすることで任意のWebページをズームできることがわかりました。それがバグなのか機能なのかわからない。それが機能として考えられているならば、どのように我々はビューポートズーミングiOS 10サファリを無効にするか?


iOS 11/12リリースで更新され、iOS 11およびiOS 12 safariはまだ_ NOTuser-scalable=noメタタグを尊重します。

mobile github site on Safari

136
Sam Su

IOS 10ではサファリでウェブページの拡大縮小を防ぐことは可能ですが、それはあなたの側でより多くの作業を伴うことになるでしょう。私は、カーゴカルト開発者がすべてのビューポートタグに "user-scalable = no"を落として、視覚障害のあるユーザーにとって不必要に物事を難しくするのをある程度困難にするのを止めるべきだと私は思います。

それでも、ダブルタップからズームを無効にする簡単な(メタタグ)方法があるように、Appleがそれらの実装を変更したいと思います。困難のほとんどはその相互作用に関連しています。

あなたはこのような何かでピンチ・ツー・ズームを止めることができます:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, false);

より深いターゲットがイベントでstopPropagationを呼び出した場合、イベントはドキュメントに到達せず、スケーリング動作はこのリスナーによって妨げられません。

ダブルタップからズームへの無効化も同様です。前のタップから300ミリ秒以内に発生したドキュメントのタップを無効にします。

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
  var now = (new Date()).getTime();
  if (now - lastTouchEnd <= 300) {
    event.preventDefault();
  }
  lastTouchEnd = now;
}, false);

フォーム要素を正しく設定していない場合は、入力に焦点を合わせると自動ズームされ、手動ズームを無効にしているため、ズームを解除することはほとんど不可能になります。入力フォントサイズが16px以上であることを確認してください。

あなたがネイティブアプリのWKWebViewでこれを解決しようとしているなら、上で与えられた解決策は実行可能ですが、これはより良い解決策です: https://stackoverflow.com/a/31943976/661418 。そして他の答えで述べたように、iOS 10 Beta 6では、Appleはメタタグを尊重するためのフラグを提供しました。

2017年5月の更新: ピンチズームを無効にする古い「タッチの長さをチェックする」方法を、よりシンプルな「touchmoveのタッチイベントをチェックする」アプローチに置き換えました。誰にとってもより信頼できるはずです。

81
Joseph

これはiOS 10の新機能です。

iOS 10 beta 1リリースノートから:

  • SafariでWebサイトのアクセシビリティを向上させるために、Webサイトでビューポートにuser-scalable=noが設定されている場合でも、ユーザーはピンチでズームすることができます。

何らかの方法でこれを無効にするためにすぐにJSアドオンが表示されることを期待しています。

76
Paul Gerarts

この振る舞いは、最近のベータ版ではおそらく変更されているようです。執筆時点ではベータ6です。

IOS 10 Beta 6のリリースノートから:

WKWebViewはデフォルトでビューポートからuser-scalable=noを尊重するようになりました。 WKWebViewのクライアントは、WKWebViewConfigurationプロパティignoresViewportScaleLimitsYESに設定することで、アクセシビリティを向上させ、ユーザーがすべてのページをピンチでズームできるようにします。

しかし、私の(非常に限られた)テストでは、私はまだそうであることを確認できません。

編集:検証済み、iOS 10 Beta 6は私にとってデフォルトでuser-scalable=noを尊重します。

14
Cellane

個々の要素の touch-action cssプロパティを使用してこれを修正することができました。リンクやボタンなど、よくクリックされる要素にtouch-action: manipulation;を設定してみてください。

13
iainbeeston

私は約1時間かけてもっと堅牢なjavascriptオプションを探しましたが、見つけられませんでした。ここ数日、 hammer.js (Hammer.jsはあらゆる種類のタッチイベントを簡単に操作できるライブラリです)をいじっていて、自分がやろうとしていたことにほとんど失敗しています。行う。

その警告と、私がJavascriptの専門家ではないことを理解しているので、これは私が思いついた解決策で、基本的にhammer.jsを利用してピンチズームとダブルタップのイベントをキャプチャし、それらを記録して破棄します。

あなたのページにhammer.jsを含めることを確認してから、このJavaScriptを頭のどこかに貼り付けてみてください。

< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >

  // SPORK - block pinch-zoom to force use of tooltip zoom
  $(document).ready(function() {

    // the element you want to attach to, probably a wrapper for the page
    var myElement = document.getElementById('yourwrapperelement');
    // create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
    var hammertime = new Hammer(myElement, {
      prevent_default: false,
      touchAction: "pan"
    });

    // pinch is not enabled by default in hammer
    hammertime.get('pinch').set({
      enable: true
    });

    // name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
    hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
      console.log('captured event:', e.type);
      e.preventDefault();
    })
  });
</script>
8
sporker

Touchoveイベントのスケールファクタをチェックしてからtouchイベントを防ぎます。

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);
6
Parmod

私はかなり素朴な解決策を思い付きましたが、それはうまくいくようです。私の目的は、アクセシビリティのためにピンチでズームを有効に保ちながら、偶発的なダブルタップがズームインとして解釈されるのを防ぐことです。

このアイデアは、ダブルタップで最初のtouchstartと2番目のtouchendの間の時間を測定し、遅延が小さすぎる場合は最後のtouchendをクリックとして解釈することです。偶然のズーミングを防ぎながら、この方法はリストのスクロールに影響を与えないように見えます。これはいいことです。私は何も見逃していないかどうかわからない。

let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;

document.addEventListener('touchstart', () => {
  preLastTouchStartAt = lastTouchStartAt;
  lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
  const touchEndAt = +new Date();
  if (touchEndAt - preLastTouchStartAt < delay) {
    event.preventDefault();
    event.target.click();
  }
});

からインスピレーションを受けて - mutewinterの要旨 および Josephの答え

5

ピンチ・ツー・ズームについて前の答えを試してみました

document.documentElement.addEventListener('touchstart', function (event) {
    if (event.touches.length > 1) {
        event.preventDefault();
    }
}, false);

ただし、 event.touches.length> 1 の場合でも画面がズームされることがあります。画面上で指が動かないように、touchmoveイベントを使用するのが最善の方法です。コードは次のようになります。

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();      
}, false);

それが役立つことを願っています。

5
Chihying Wu

1つのスタイルルールを挿入してズームイベントをインターセプトすることで、必要なものすべてを取得できます。

$(function () {
  if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
  $(document.head).append(
    '<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
  )
  $(window).on('gesturestart touchmove', function (evt) {
    if (evt.originalEvent.scale !== 1) {
      evt.originalEvent.preventDefault()
      document.body.style.transform = 'scale(1)'
    }
  })
})

✔ピンチズームを無効にします。

✔ダブルタップズームを無効にします。

✔スクロールは影響を受けません。

✔タップハイライトを無効にします(iOSではスタイルルールによってトリガーされます)。

注意:iOS検出を好みに合わせて微調整してください。それについての詳細 ここ


lukejackson および Piotr Kowalski への謝罪、その答えは上のコードでは修正された形式で表示されます。

4
jeff_mcmahan

これを書いている時点でMobile Safariで機能する回避策は、addEventListenerの3番目の引数を{ passive: false }にすることです。したがって、完全な回避策は次のようになります。

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

オプションがサポートされているかどうかを確認します 後方互換性を保つために/ /.

3

私の特定のケースでは、3Dシーンを作成するためにBabylon.jsを使用しています。私のページ全体は1つのフルスクリーンキャンバスで構成されています。 3Dエンジンには独自のズーミング機能がありますが、iOSではピンチツーズームがそれを妨げます。私は自分の問題を克服するために@Josephの回答を更新しました。無効にするには、イベントリスナのオプションとして{passive:false}を渡す必要があると考えました。次のコードは私のために働きます:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);
2
Hamed

意図しないズームは、次の場合に発生する傾向があります。

  • ユーザーがインターフェイスのコンポーネントをダブルタップします
  • ユーザーは2つ以上の数字(ピンチ)を使用してビューポートと対話します

ダブルタップの動作を防ぐために、2つの非常に簡単な回避策を見つけました。

<button onclick='event.preventDefault()'>Prevent Default</button>
<button style='touch-action: manipulation'>Touch Action Manipulation</button>

これらはどちらも、Safari(iOS 10.3.2)がボタン上でズームすることを防ぎます。ご覧のとおり、1つはJavaScriptのみであり、もう1つはCSSのみです。適切に使用してください。

以下にデモを示します。 https://codepen.io/lukejacksonn/pen/QMELXQ

主にウェブ用のマルチタッチインターフェイスを作成しない傾向があるため、ピンチ動作を(まだ)防止しようとしませんでした。次に、ネイティブアプリUIを含むすべてのインターフェイスを「ピンチしてズーム」する必要があるという考えに至りました。 -場所で可能。ユーザーを使用してUIをユーザーがアクセスできるようにすることを、あらゆるコストで回避するように設計します。

1
lukejacksonn

ダブルクリックでズームできないように見えるこの簡単な回避策が見つかりました。

    // Convert touchend events to click events to work around an IOS 10 feature which prevents
    // developers from using disabling double click touch zoom (which we don't want).
    document.addEventListener('touchend', function (event) {
        event.preventDefault();
        $(event.target).trigger('click');
    }, false);
1
Syntax

おかしなことに、少なくともiOS 10.2のSafariでは、要素またはその上位オブジェクトのいずれかに次のいずれかがある場合、ダブルタップしてズームすることは魔法のように無効になっています。

  1. OnClickリスナー - それは簡単なことです。
  2. CSSで設定されたcursor: pointer
1
mariomc

これは私のために働いた:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false);

私はiOS(iPhone 6、iOS 10.0.2)の私のページで実際に上記のすべての答えをチェックしましたが、成功しませんでした。これが私の実用的な解決策です。

$(window).bind('gesturestart touchmove', function(event) {
    event = event.originalEvent || event;
    if (event.scale !== 1) {
         event.preventDefault();
         document.body.style.transform = 'scale(1)'
    }
});
0
Piotr Kowalski

上記のいずれも機能しない場合は、ボックスのフォントサイズを16pxに設定するだけで問題が解決します。

0
Jamie Burton