désactiver la fenêtre d'affichage zoom iOS 10+ safari?

j'ai mis à jour mon iPhone 6 plus à la version iOS 10 beta et je viens de découvrir que dans le safari mobile, vous pouvez zoomer sur toutes les pages Web en tapant deux fois ou en pincant ignorer le code user-scalable=no dans la balise meta. Je ne sais pas si c'est un bug ou une fonctionnalité. Si c'est considéré comme une fonctionnalité, comment désactiver viewport zooming iOS 10 safari ?


mise à jour sur iOS 11 version, iOS 11 safari toujours PAS respecter la balise user-scalable=no meta.

mobile github site on Safari

115
demandé sur Sam Su 2016-06-14 12:32:48

15 réponses

il est possible d'empêcher la mise à l'échelle de la page Web dans iOS 10, mais cela va impliquer plus de travail de votre part. Je suppose que l'argument est qu'un certain degré de difficulté devrait empêcher les devs cargo-cult de laisser tomber "user-scalable=no" dans chaque étiquette de viewport et de rendre les choses inutilement difficiles pour les utilisateurs ayant une déficience visuelle.

toujours, je voudrais voir Apple changer leur implémentation afin qu'il y ait un moyen simple (meta-tag) de désactiver le double-tap-to-zoom. La plupart des difficultés sont liées à l'interaction.

vous pouvez arrêter pinch-to-zoom avec quelque chose comme ceci:

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

notez que si des cibles plus profondes appellent stopPropagation sur l'événement, l'événement n'atteindra pas le document et le comportement de mise à l'échelle ne sera pas empêché par cet auditeur.

désactiver le double-tap-to-zoom est similaire. Vous désactivez tout robinet sur le document se produisant dans les 300 millisecondes du robinet précédent:

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

si vous ne configurez pas correctement les éléments de votre formulaire, en se concentrant sur une entrée, vous ferez un zoom automatique, et puisque vous avez désactivé le zoom manuel, il sera maintenant presque impossible de désamorcer. Assurez-vous que la taille de la police d'entrée est >= 16px.

si vous essayez de résoudre cela dans une WKWebView dans une application native, la solution donnée ci-dessus est viable, mais c'est une meilleure solution: https://stackoverflow.com/a/31943976/661418 . Et comme mentionné dans d'autres réponses, dans iOS 10 beta 6, Apple a maintenant fourni un drapeau pour honorer la balise meta.

mise à jour mai 2017: j'ai remplacé l'ancienne méthode" check touches length on touchstart "pour désactiver pinch-zoom par un simple "check event".l'échelle sur touchmove' approche. Devrait être plus fiable pour tout le monde.

74
répondu Joseph 2017-05-23 21:13:33

c'est une nouveauté dans iOS 10.

de l'iOS 10 beta 1 Notes de mise à jour:

  • pour améliorer l'accessibilité sur les sites Web en Safari, les utilisateurs peuvent maintenant pincer-to-zoom même quand un site web met user-scalable=no dans le viewport.

Je m'attends à ce que nous allons voir un js add-on bientôt pour désactiver ceci d'une certaine façon.

73
répondu Paul Gerarts 2016-06-16 12:24:54

il semble que ce comportement soit supposé changer dans la dernière version bêta, qui au moment de la rédaction est bêta 6.

Dans les notes de version pour iOS 10 Beta 6:

WKWebView maintenant par défaut à respecter user-scalable=no à partir d'un viewport. Les Clients de WKWebView peuvent améliorer l'accessibilité et permettre aux utilisateurs de pincer pour zoomer sur toutes les pages par le WKWebViewConfiguration biens ignoresViewportScaleLimits à YES .

cependant, dans mes tests (très limités), Je ne peux pas encore confirmer que c'est le cas.

Edit: vérifié, iOS 10 Beta 6 égards user-scalable=no par défaut pour moi.

12
répondu Cellane 2016-08-18 13:31:03

j'ai pu corriger cela en utilisant la propriété touch-action css sur des éléments individuels. Essayez de définir touch-action: manipulation; sur des éléments qui sont généralement cliqués sur, comme des liens ou des boutons.

11
répondu iainbeeston 2017-01-18 14:40:25

j'ai passé environ une heure à chercher une option javascript plus robuste, et je n'en ai pas trouvé. Il se trouve que ces derniers jours, j'ai joué avec le marteau .js (le Marteau.js est une bibliothèque qui vous permet de manipuler toutes sortes d'événements tactiles facilement), et surtout à défaut, à ce que j'essayais de faire.

avec cette mise en garde, et en comprenant que je ne suis pas un expert en javascript, c'est une solution que j'ai trouvé qui utilise essentiellement marteau.js pour capturer les évènements pinch-zoom et double-tap, puis les enregistrer et les jeter.

assurez-vous d'inclure le marteau.js dans votre page et ensuite essayer de coller ce javascript dans la tête quelque part:

< 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>
6
répondu sporker 2017-09-05 10:15:41

j'ai essayé la réponse précédente sur pinch-to-zoom

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

cependant parfois l'écran zoome encore lorsque l'événement .toucher.Longueur > 1 J'ai trouvé le meilleur moyen est d'utiliser touchmove événement, afin d'éviter n'importe quel doigt se déplaçant sur l'écran. Le code ressemblera à ceci:

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

j'Espère que ça aidera.

5
répondu Chihying Wu 2016-09-20 12:38:00

Vérifier le facteur d'échelle dans l'événement touchove puis prévenir l'événement touch.

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);
5
répondu Parmod 2017-01-11 10:04:12

nous pouvons obtenir tout ce que nous voulons en injectant une règle de style et en interceptant les événements de zoom:

$(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)'
    }
  })
})

✔ désactive pinch zoom.

✔ désactive Double-Tap zoom.

✔ le rouleau N'est pas affecté.

✔ désactive tap highlight (qui est déclenché, sur iOS, par la règle de style).

avis: modifier la détection iOS à votre convenance. En savoir plus sur ce ici .


"151910920 des" Excuses lukejackson et Piotr Kowalski , dont les réponses apparaissent sous une forme modifiée, dans le code ci-dessus.

4
répondu jeff_mcmahan 2017-08-04 00:06:24

j'ai trouvé une solution assez naïve, mais elle semble fonctionner. Mon but était d'éviter que des doubles-tapes accidentelles soient interprétées comme un zoom avant, tout en maintenant pinch to zoom travailler pour l'accessibilité.

l'idée est de mesurer le temps entre le premier touchstart et le second touchend dans un double robinet, puis d'interpréter le dernier touchend comme un clic si le délai est trop petit. Tout en empêchant le zoom accidentel, cette méthode semble garder liste scrolling pas affectés, ce qui est agréable. Vous ne savez pas si je n'ai rien manqué.

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();
  }
});

Inspiré par un l'essentiel de mutewinter et Joseph réponse .

3
répondu Alexander Kachkaev 2017-10-07 19:07:47

aussi étrange que cela paraisse, au moins pour le Safari dans iOS 10.2, double tap to zoom est désactivé par magie si votre élément ou l'un de ses ancêtres ont l'un des suivants:

  1. onClick de l'écoute, il peut être une simple noop.
  2. Un cursor: pointer définir en CSS
1
répondu mariomc 2017-01-12 18:57:28

trouvé ce travail simple autour qui semble empêcher double clic pour zoom:

    // 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
répondu Syntax 2017-10-03 07:33:45

dans mon cas particulier, J'utilise Babylone.js pour créer une scène 3D et toute ma page se compose d'une toile plein écran. Le moteur 3D a sa propre fonctionnalité de zoom mais sur iOS le pincement-à-zoom interfère avec cela. J'ai mis à jour la réponse de @Joseph pour surmonter mon problème. Pour le désactiver, j'ai compris que j'avais besoin de passer le {passive: false} comme une option à l'écouteur d'événement. Le code suivant fonctionne pour moi:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);
1
répondu Hamed 2018-06-12 18:17:02

j'ai vérifié toutes les réponses ci-dessus dans la pratique avec ma page sur iOS (iPhone 6, iOS 10.0.2), mais sans succès. C'est ma solution de travail:

$(window).bind('gesturestart touchmove', function(event) {
    event = event.originalEvent || event;
    if (event.scale !== 1) {
         event.preventDefault();
         document.body.style.transform = 'scale(1)'
    }
});
0
répondu Piotr Kowalski 2017-07-27 13:40:30

non intentionnel zoom tend à se produire lorsque:

  • Un utilisateur double appuie sur un composant de l'interface
  • un utilisateur interagit avec le viewport en utilisant deux ou plusieurs chiffres (pincement)

pour prévenir le double tap comportement j'ai trouvé deux solutions très simples:

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

tous deux empêchent le Safari (iOS 10.3.2) de zoomant sur le bouton. Comme vous pouvez le voir l'un est JavaScript seulement, L'autre est CSS seulement. Utiliser de façon appropriée.

Voici une démo: https://codepen.io/lukejacksonn/pen/QMELXQ

Je n'ai pas essayé d'empêcher le comportement de pincement (encore), principalement parce que j'ai tendance à ne pas créer des interfaces multi-touch pour le web et deuxièmement je suis arrivé à l'idée que peut-être toutes les interfaces y compris app UI natif devrait être "pincer pour zoomer" - Capable dans les endroits. Je voudrais encore concevoir pour éviter l'utilisateur d'avoir de faire ceci pour rendre votre UI accessible à eux, à tout prix.

0
répondu lukejacksonn 2017-08-01 16:03:40

la solution qui fonctionne dans le Safari Mobile à ce moment de l'écriture, est d'avoir le troisième argument dans adddEventListener être { passive: false } , donc la solution complète ressemble à ceci:

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

vous pouvez vouloir vérifier si les options sont supportées pour rester compatible à l'envers.

0
répondu Casper Fabricius 2018-08-06 15:01:40