98 votes

Comment réinitialiser l'échelle/zoom d'une application web lors d'un changement d'orientation sur l'iPhone ?

Lorsque je lance mon application en mode portrait, elle fonctionne bien. Puis je passe en mode paysage et elle est mise à l'échelle. Pour que l'échelle soit correcte en mode paysage, je dois double-cliquer deux fois sur un élément, d'abord pour effectuer un zoom avant complet (comportement normal du double-cliquer), puis pour effectuer un zoom arrière complet (comportement normal du double-cliquer). Lorsque le zoom arrière est effectué, il est ramené à la NOUVELLE échelle correcte pour le mode paysage.

Le passage en mode portrait semble fonctionner de manière plus cohérente, c'est-à-dire qu'il gère le zoom de manière à ce que l'échelle soit correcte lorsque l'orientation repasse en mode portrait.

J'essaie de savoir s'il s'agit d'un bogue ou d'un problème qui peut être résolu avec JavaScript.

Dans le méta-contenu de la fenêtre d'affichage, je fixe l'échelle initiale à 1.0 et je ne fixe PAS d'échelle minimale ou maximale (et je ne veux pas le faire). Je fixe la largeur à device-width.

Des idées ? Je sais que beaucoup de personnes seraient reconnaissantes d'avoir une solution car il semble que ce soit un problème persistant.

1 votes

Une solution parfaite : Pas de javascript ! stackoverflow.com/a/8727440/805787

89voto

snobojohan Points 1871

Jeremy Keith ( @adactio ) a une bonne solution pour cela sur son blog Orientation et échelle

Gardez le balisage évolutif en ne fixant pas d'échelle maximale dans le balisage.

<meta name="viewport" content="width=device-width, initial-scale=1">

Ensuite, désactivez l'extensibilité avec javascript sur le chargement jusqu'à ce que gesturestart lorsque vous autorisez à nouveau l'extensibilité avec ce script :

if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) {
        viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
        document.body.addEventListener('gesturestart', function () {
            viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
        }, false);
    }
}

Mise à jour 22-12-2014 :
Sur un iPad 1, cela ne fonctionne pas, il échoue sur l'eventlistener. J'ai découvert que la suppression de .body répare ça :

document.addEventListener('gesturestart', function() { /* */ });

4 votes

C'est sûrement mieux que de désactiver le zoom ! La meilleure solution que j'ai trouvée jusqu'à présent :)

0 votes

Hmm, cela désactive toujours la possibilité de zoomer. Est-ce que quelqu'un a une solution simple qui ne fait pas cela ?

0 votes

Cela fonctionne, mais j'ai observé que le problème recommence si j'utilise le geste de pincer-zoomer puis de faire pivoter l'écran. Je ne sais pas comment le résoudre.

18voto

Andrew Ashbacher Points 739

Scott Jehl a mis au point une solution fantastique qui utilise l'accéléromètre pour anticiper les changements d'orientation. Cette solution est très réactive et n'interfère pas avec les gestes de zoom.

https://github.com/scottjehl/iOS-Orientationchange-Fix

Comment ça marche : Cette solution fonctionne en écoutant l'accéléromètre de l'appareil. pour prédire quand un changement d'orientation est sur le point de se produire. Lorsqu'il juge qu'un changement d'orientation est imminent, le script désactive les fonctions de utilisateur, ce qui permet au changement d'orientation de se produire correctement, avec le le zoom désactivé. Le script restaure à nouveau le zoom une fois que le dispositif est soit orienté près de la verticale, soit après que son orientation ait changé. De cette façon, le zoom de l'utilisateur n'est jamais désactivé pendant que la page est en utilisation.

Source réduite :

/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT License.*/(function(m){if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1)){return}var l=m.document;if(!l.querySelector){return}var n=l.querySelector("meta[name=viewport]"),a=n&&n.getAttribute("content"),k=a+",maximum-scale=1",d=a+",maximum-scale=10",g=true,j,i,h,c;if(!n){return}function f(){n.setAttribute("content",d);g=true}function b(){n.setAttribute("content",k);g=false}function e(o){c=o.accelerationIncludingGravity;j=Math.abs(c.x);i=Math.abs(c.y);h=Math.abs(c.z);if(!m.orientation&&(j>7||((h>6&&i<8||h<8&&i>6)&&j>5))){if(g){b()}}else{if(!g){f()}}}m.addEventListener("orientationchange",f,false);m.addEventListener("devicemotion",e,false)})(this);

0 votes

Joli ! On dirait une solution élégante.

1 votes

Ceci devrait être la réponse acceptée !!!! J'aurais aimé voir cela avant de perdre une heure à chercher les solutions ci-dessus :)

1 votes

Après d'autres tests, cette solution n'est pas très fiable :( elle est incohérente, et après avoir parcouru le code, je peux comprendre pourquoi... le "seuil" de mouvement défini n'est pas toujours atteint, surtout si vous tenez l'ipad à un angle pendant la rotation.

13voto

rakaloof Points 437

J'ai eu le même problème, et le réglage de maximum-scale=1.0 a fonctionné pour moi.

Modifier : Comme mentionné dans les commentaires, cela désactive le zoom utilisateur sauf lorsque le contenu dépasse la largeur-résolution. Comme mentionné, cela peut ne pas être judicieux. Cela peut aussi être souhaité dans certains cas.

Le code de la fenêtre de visualisation :

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;">

0 votes

Bonne solution. Elle permet de maintenir la page à un niveau de zoom constant (par rapport à la largeur de l'appareil) malgré les changements d'orientation. Merci de l'avoir partagée !

18 votes

L'inconvénient est que les utilisateurs handicapés ne peuvent pas zoomer sur votre site !

0 votes

J'ai remarqué que toutes ces méthodes semblent empêcher les CSS basées sur la requête média d'enregistrer correctement la nouvelle largeur du périphérique (ex : @media all and (max-width : 479px))

3voto

psyder Points 31

Si la largeur est définie dans la fenêtre d'affichage :

<meta name = "viewport" content = "width=device-width; initial-scale=1.0;
 maximum-scale=1.0;" />

Et puis changez l'orientation, il y aura parfois un zoom aléatoire (surtout si vous faites glisser sur l'écran). Pour résoudre ce problème, ne définissez pas de largeur ici, j'ai utilisé :

<meta id="viewport" name="viewport" content="initial-scale=1.0; user-scalable=0;
minimum-scale=1.0; maximum-scale=1.0" />

Cela corrige le zoom ; quoi qu'il arrive, vous pouvez utiliser l'événement window.onorientationchange ou, si vous voulez que cela soit indépendant de la plate-forme (pratique pour les tests), l'événement window.onorientationchange. largeur intérieure de la fenêtre méthode.

0 votes

Cela empêcherait-il également les utilisateurs de faire un zoom avant et arrière manuellement ?

1voto

Avi Flax Points 14898

MobileSafari prend en charge le orientationchange sur l'événement window objet. Malheureusement, il ne semble pas y avoir de moyen de contrôler directement le zoom via JavaScript. Peut-être pourriez-vous écrire/modifier dynamiquement l'objet meta qui contrôle la fenêtre d'affichage - mais je doute que cela fonctionne, car cela n'affecte que l'état initial de la page. Vous pourriez peut-être utiliser cet événement pour redimensionner votre contenu à l'aide de CSS. Bonne chance !

3 votes

Merci. Oui, j'ai essayé de modifier dynamiquement les valeurs de la balise méta viewport et cela n'a rien donné. Il me semble que si vous effectuez une rotation en mode paysage, vous voulez que le zoom soit correct afin de conserver l'échelle pour que la page tienne dans la fenêtre de Safari. Il me semble très étrange que ce ne soit pas le comportement par défaut !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X