it-swarm.com.de

Wie kann ich den Maßstab/Zoom einer Web-App bei einer Orientierungsänderung auf dem iPhone zurücksetzen?

Wenn ich meine App im Portrait-Modus starte, funktioniert sie einwandfrei. Dann drehe ich mich in die Landschaft und es wird vergrößert. Um es für den Querformat-Modus richtig zu skalieren, tippe ich zweimal auf etwas zweimal. Zuerst ganz hineinzoomen (normales Doppeltipp-Verhalten) und noch einmal ganz herauszoomen (wieder normales Doppeltipp-Verhalten) . Wenn es verkleinert wird, zoomt es auf den korrekten NEUEN Maßstab für den Querformatmodus.

Der Wechsel zum Portrait scheint konsistenter zu sein. Das heißt, der Zoom wird so behandelt, dass der Maßstab korrekt ist, wenn die Ausrichtung wieder in Hochformat geändert wird.

Ich versuche herauszufinden, ob das ein Fehler ist? oder wenn dies etwas ist, das mit JavaScript behoben werden kann?

Mit dem Viewport-Meta-Inhalt setze ich die Anfangsskala auf 1,0 und ich setze KEINE Minimal- oder Maximalskala ein (ich möchte auch nicht). Ich stelle die Breite auf Gerätebreite ein.

Irgendwelche Ideen? Ich weiß, dass viele Leute dankbar wären, eine Lösung zu haben, da dies ein anhaltendes Problem zu sein scheint.

92
Elisabeth

Jeremy Keith ( @ adactio ) hat dafür eine gute Lösung auf seinem Blog Orientierung und Skala

Halten Sie das Markup skalierbar, indem Sie kein Maximum für das Markup festlegen.

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

Deaktivieren Sie dann die Skalierbarkeit mit Javascript beim Laden, bis gesturestart , wenn Sie die Skalierbarkeit mit diesem Skript wieder zulassen:

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

Update 22-12-2014:
Auf einem iPad 1 funktioniert dies nicht, es schlägt auf dem Eventlistener fehl. Ich habe festgestellt, dass das Entfernen von .body Folgendes behebt:

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

Scott Jehl hat eine fantastische Lösung gefunden, die den Beschleunigungssensor verwendet, um Orientierungsänderungen vorwegzunehmen. Diese Lösung reagiert sehr schnell und stört die Zoomgesten nicht.

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

Wie es funktioniert: Dieses Update funktioniert, indem Sie auf .__ des Geräts hören. Beschleunigungsmesser, um vorherzusagen, wann eine Orientierungsänderung auftritt . Wenn eine Änderung der Ausrichtung für unmittelbar bevorsteht, deaktiviert das Skript den Benutzer Zoomen, so dass die Ausrichtungsänderung mit .__ korrekt ausgeführt wird. Zoomen deaktiviert. Das Skript stellt den Zoom wieder her, sobald das Gerät .__ ist. entweder nahe an aufrecht stehend orientiert, oder nachdem seine Ausrichtung geändert. Auf diese Weise wird das Zoomen der Benutzer niemals deaktiviert, wenn sich die Seite in .__ befindet. benutzen.

Minifizierte Quelle:

/*! 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);
18

Ich hatte das gleiche Problem und die Einstellung der Maximum-Skala = 1.0 hat für mich funktioniert.

Bearbeiten: Wie in den Kommentaren erwähnt, wird der Benutzerzoom deaktiviert, außer wenn der Inhalt die Breitenauflösung überschreitet. Wie gesagt, das mag nicht klug sein. In manchen Fällen kann es auch erwünscht sein.

Der Viewport-Code:

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

Wenn Sie die Breite im Ansichtsfenster festgelegt haben:

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

Und dann ändern Sie die Ausrichtung, in die manchmal zufällig hineingezoomt wird (insbesondere wenn Sie auf dem Bildschirm ziehen), um dies zu korrigieren. Legen Sie hier keine Breite fest, die ich verwendet habe:

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

Dies behebt den Zoom, egal was passiert, dann können Sie entweder das window.onorientationchange -Ereignis verwenden oder wenn Sie möchten, dass es plattformunabhängig ist (praktisch zum Testen) der Methode window.innerWidth .

3
psyder

Ich habe diese Funktion in meinem Projekt verwendet.

function changeViewPort(key, val) {
    var reg = new RegExp(key, "i"), oldval = document.querySelector('meta[name="viewport"]').content;
    var newval = reg.test(oldval) ? oldval.split(/,\s*/).map(function(v){ return reg.test(v) ? key+"="+val : v; }).join(", ") : oldval+= ", "+key+"="+val ;
    document.querySelector('meta[name="viewport"]').content = newval;
}

also einfach addEventListener:

if( /iPad|iPhone|iPod|Android/i.test(navigator.userAgent) ){
    window.addEventListener("orientationchange", function() { 
        changeViewPort("maximum-scale", 1);
        changeViewPort("maximum-scale", 10);
    }
}
1
James Yang

MobileSafari unterstützt das Ereignis orientationchange für das Objekt window. Leider scheint es keine Möglichkeit zu geben, den Zoom direkt über JavaScript zu steuern. Vielleicht könnten Sie das meta-Tag, das den Viewport steuert, dynamisch schreiben/ändern - aber ich bezweifle, dass dies funktionieren würde, es beeinflusst nur den Anfangszustand der Seite. Vielleicht könnten Sie dieses Ereignis verwenden, um die Größe Ihres Inhalts mithilfe von CSS tatsächlich zu ändern. Viel Glück!

1
Avi Flax

Ich habe eine Arbeitsdemo eines Landschafts-/Hochformat-Layouts erstellt, aber der Zoom muss deaktiviert sein, damit er ohne JavaScript funktioniert:

http://matthewjamestaylor.com/blog/ipad-layout-with-landscape-portrait-modes

Ich habe eine neue Problemumgehung gefunden, die sich von allen anderen, die ich gesehen habe, unterscheidet, indem der native iOS-Zoom deaktiviert und stattdessen die Zoomfunktion in JavaScript implementiert wird.

Ein hervorragender Hintergrund für die verschiedenen anderen Lösungen des Zoom-/Orientierungsproblems ist von Sérgio Lopes: Ein Fix für den bekannten iOS-Zoom-Fehler bei der Ausrichtung zu Hochformat .

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" id="viewport" content="user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
    <title>Robocat mobile Safari zoom fix</title>
    <style>
        body {
            padding: 0;
            margin: 0;
        }
        #container {
            -webkit-transform-Origin: 0px 0px;
            -webkit-transform: scale3d(1,1,1);
            /* shrink-to-fit needed so can measure width of container http://stackoverflow.com/questions/450903/make-css-div-width-equal-to-contents */
            display: inline-block;
            *display: inline;
            *zoom: 1;
        }
        #zoomfix {
            opacity: 0;
            position: absolute;
            z-index: -1;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <input id="zoomfix" disabled="1" tabIndex="-1">
    <div id="container">
        <style>
            table {
                counter-reset: row cell;
                background-image: url(http://upload.wikimedia.org/wikipedia/commons/3/38/JPEG_example_JPG_RIP_010.jpg);
            }
            tr {
                counter-increment: row;
            }
            td:before {
                counter-increment: cell;
                color: white;
                font-weight: bold;
                content: "row" counter(row) ".cell" counter(cell);
            }
        </style>
        <table cellspacing="10">
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
            <tr><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td><td>
        </table>
    </div>

    <script>
    (function() {
        var viewportScale = 1;
        var container = document.getElementById('container');
        var scale, originX, originY, relativeOriginX, relativeOriginY, windowW, windowH, containerW, containerH, resizeTimer, activeElement;
        document.addEventListener('gesturestart', function(event) {
            scale = null;
            originX = event.pageX;
            originY = event.pageY;
            relativeOriginX = (originX - window.pageXOffset) / window.innerWidth;
            relativeOriginY = (originY - window.pageYOffset) / window.innerHeight;
            windowW = window.innerWidth;
            windowH = window.innerHeight;
            containerW = container.offsetWidth;
            containerH = container.offsetHeight;
        });
        document.addEventListener('gesturechange', function(event) {
            event.preventDefault();
            if (originX && originY && event.scale && event.pageX && event.pageY) {
                scale = event.scale;
                var newWindowW = windowW / scale;
                if (newWindowW > containerW) {
                    scale = windowW / containerW;
                }
                var newWindowH = windowH / scale;
                if (newWindowH > containerH) {
                    scale = windowH / containerH;
                }
                if (viewportScale * scale < 0.1) {
                    scale = 0.1/viewportScale;
                }
                if (viewportScale * scale > 10) {
                    scale = 10/viewportScale;
                }
                container.style.WebkitTransformOrigin = originX + 'px ' + originY + 'px';
                container.style.WebkitTransform = 'scale3d(' + scale + ',' + scale + ',1)';
            }
        });
        document.addEventListener('gestureend', function() {
            if (scale && (scale < 0.95 || scale > 1.05)) {
                viewportScale *= scale;
                scale = null;
                container.style.WebkitTransform = '';
                container.style.WebkitTransformOrigin = '';
                document.getElementById('viewport').setAttribute('content', 'user-scalable=no,initial-scale=' + viewportScale + ',minimum-scale=' + viewportScale + ',maximum-scale=' + viewportScale);
                document.body.style.WebkitTransform = 'scale3d(1,1,1)';
                // Without zoomfix focus, after changing orientation and zoom a few times, the iOS viewport scale functionality sometimes locks up (and completely stops working).
                // The reason I thought this hack would work is because showing the keyboard is the only way to affect the viewport sizing, which forces the viewport to resize (even though the keyboard doesn't actually get time to open!).
                // Also discovered another amazing side effect: if you have no meta viewport element, and focus()/blur() in gestureend, zoom is disabled!! Wow!
                var zoomfix = document.getElementById('zoomfix');
                zoomfix.disabled = false;
                zoomfix.focus();
                zoomfix.blur();
                setTimeout(function() {
                    zoomfix.disabled = true;
                    window.scrollTo(originX - relativeOriginX * window.innerWidth, originY - relativeOriginY * window.innerHeight);
                    // This forces a repaint. repaint *intermittently* fails to redraw correctly, and this fixes the problem.
                    document.body.style.WebkitTransform = '';
                }, 0);
            }
        });
    })();
    </script>
</body>
</html>

Es könnte verbessert werden, aber für meine Bedürfnisse werden die größten Nachteile vermieden, die bei allen anderen Lösungen auftreten, die ich gesehen habe. Bisher habe ich es nur mit Mobile Safari auf einem iPad 2 mit iOS4 getestet.

Der Fokus ()/Unschärfe () ist eine Problemumgehung, um das gelegentliche Blockieren der Zoomfunktion zu verhindern, das auftreten kann, wenn die Ausrichtung geändert und das Zoomen einige Male vergrößert wird.

Wenn Sie den document.body.style einstellen, wird eine Neuformulierung des gesamten Bildschirms erzwungen, wodurch gelegentlich auftretende Probleme vermieden werden, bei denen die Neuformulierung nach dem Zoomen stark fehlschlägt.

0
robocat

Elisabeth Sie können den Inhalt des Ansichtsfensters dynamisch ändern, indem Sie die Eigenschaft "id" zum Metatag hinzufügen:

<meta name="viewport" id="view" content="user-scalable=yes, width=device-width minimum-scale=1, maximum-scale=1" />

Dann kannst du einfach per Javascript anrufen: 

document.getElementById("view").setAttribute('content','user-scalable=yes, width=device-width, minimum-scale=1, maximum-scale=10');
0
M Penades

Hier ist eine andere Möglichkeit, die gut zu funktionieren scheint.

  1. Legen Sie das Meta-Tag fest, um den Viewport auf scale = 1 zu beschränken, wodurch das Zoomen verhindert wird:

    <meta name = "viewport" content = "width = Gerätebreite, anfängliche Skala = 1, minimale Skala = 1, maximale Skala = 1">

  2. Ändern Sie bei Javascript das Meta-Tag eine halbe Sekunde später in Zoomen zulassen:

    setTimeout (function () {document.querySelector ("meta [name = viewport]"). setAttribute ('content', 'width = Gerätebreite, Anfangsskala = 1');}, 500);

  3. Laden Sie die Seite erneut mit Javascript, um die Seite neu zu laden:

    window.onorientationchange = function () {window.location.reload ();};

Bei jeder Neuausrichtung des Geräts wird die Seite zunächst ohne Zoom neu geladen. Eine halbe Sekunde später ist die Fähigkeit zum Zoomen wiederhergestellt. 

0
Mark Lamprey

Ein sehr einfach zu implementierender Fix gefunden. Setzen Sie den Fokus auf ein Textelement mit einer Schriftgröße von 50px, wenn Sie das Formular ausfüllen. Es scheint nicht zu funktionieren, wenn das Textelement ausgeblendet ist. Das Ausblenden dieses Elements lässt sich jedoch leicht durchführen, indem die Farbeigenschaften der Elemente so festgelegt werden, dass sie keine Deckkraft haben. 

0
Dellsmash