it-swarm.com.de

Einstellen des Ansichtsfensters auf Breite und Höhe

Ich arbeite an einer Website, die in eine bestimmte Breite und Höhe passt (ein 885x610 div mit 1px-Rand und 3px-Rand). Ich möchte, dass der Benutzer niemals scrollen oder zoomen muss, um das gesamte Div anzuzeigen. es sollte immer vollständig sichtbar sein. Da Geräte über eine Vielzahl von Auflösungen und Seitenverhältnissen verfügen, kam die Idee auf, den Metaplayer "Viewport" mit JavaScript dynamisch festzulegen. Auf diese Weise hat das div immer die gleichen Abmessungen. Verschiedene Geräte müssen unterschiedlich vergrößert werden, um das gesamte div in ihrem Ansichtsfenster anzupassen. Ich habe meine Idee ausprobiert und einige seltsame Ergebnisse erhalten.

Der folgende Code funktioniert beim ersten Laden der Seite (getestet in Chrome 32.0.1700.99 unter Android 4.4.0). Beim Aktualisieren ändert sich jedoch die Zoomstufe. Wenn ich alert auskommentiere, funktioniert es auch nicht beim ersten Laden der Seite.

Fiddle

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
        <script type="text/javascript">
            function getViewportWidth() {
                if (window.innerWidth) {
                    return window.innerWidth;
                }
                else if (document.body && document.body.offsetWidth) {
                    return document.body.offsetWidth;
                }
                else {
                    return 0;
                }
            }

            function getViewportHeight() {
                if (window.innerHeight) {
                    return window.innerHeight;
                }
                else if (document.body && document.body.offsetHeight) {
                    return document.body.offsetHeight;
                }
                else {
                    return 0;
                }
            }

            if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
                var actual_width = getViewportWidth();
                var actual_height = getViewportHeight();

                var min_width = 887;
                var min_height = 615;

                var ratio = Math.min(actual_width / min_width, actual_height / min_height);

                if (ratio < 1) {
                    document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + ratio + ', maximum-scale=' + ratio + ', minimum-scale=' + ratio + ', user-scalable=yes, width=' + actual_width);
                }
            }

            alert(document.querySelector('meta[name="viewport"]').getAttribute('content'));
        </script>
        <title>Test</title>
        <style>
            body {
                margin: 0;
            }

            div {
                margin: 3px auto 0;
                width: 885px;
                height: 610px;
                border: 1px solid #f00;
                background-color: #fdd;
            }
        </style>
    </head>
    <body>
        <div>
            This div is 885x610 (ratio is in between 4:3 and 16:10) with a 1px border and 3px top margin, making a total of 887x615.
        </div>
    </body>
</html>

Was kann ich tun, damit diese Website an die Breite und Höhe angepasst werden kann?

10
Nick

Es ist möglich, ein konsistentes Verhalten zu erhalten. Es ist aber leider sehr komplex. Ich arbeite an einem Skript, das gefälschte Agenten erkennt und den Ansichtsbereich dem Desktop oder anderen gefälschten Agenten entsprechend dynamisch neu skaliert. Ich hatte auch Probleme mit dem Zoomen bei Android/Chrome sowie dem iOS-Emulator ...

Um dies zu umgehen, müssen Sie das Zoomen deaktivieren und/oder das Ansichtsfenster zweimal einstellen. Beim ersten Durchlauf, vorzugsweise inline im <head>, wie Sie dies jetzt tun, legen Sie die Skalierung fest und deaktivieren die Benutzerskalierung vorübergehend, um das Zoomproblem zu vermeiden, und verwenden für alle drei Skalen denselben festen Wert:

document.querySelector('meta[name=viewport]').setAttribute('content', 'width='+width+',minimum-scale='+scale+',maximum-scale='+scale+',initial-scale='+scale);

Um das Zoomen wieder herzustellen, setzen Sie das Ansichtsfenster mit derselben Skalierung erneut auf DOMContentLoaded, mit der Ausnahme, dass Sie diesmal normale Min/Max-Skalierungswerte zum Wiederherstellen der Benutzerskalierung festlegen:

document.querySelector('meta[name=viewport]').setAttribute('content', 'width='+width+',minimum-scale=0,maximum-scale=10');

In Ihrem Kontext ist initial-scale='+scale möglicherweise für eine bessere Alternative für DOMContentLoaded erforderlich, da das Layout fest und größer als der Darstellungsbereich ist:

document.querySelector('meta[name=viewport]').setAttribute('content', 'width='+width+',minimum-scale=0,maximum-scale=10,initial-scale='+scale);

Dadurch sollte das Ansichtsfenster so skaliert werden, wie Sie es in Webkit-Browsern ohne Zoomprobleme möchten. Ich sage nur in webkit, weil leider IE und Firefox das Ändern des Ansichtsfensters nicht unterstützen, wie in dieser Browser-Kompatibilitätstabelle für Ansichtsfenster, Abmessungen und Pixelwerte für Geräte angezeigt wird: http://www.quirksmode.org/mobile/ tableViewport.html

IE hat seinen eigenen Weg, den Viewport dynamisch zu ändern, was tatsächlich für die Reaktion von IE -Schnappmodi erforderlich ist http://timkadlec.com/2012/10/ie10-snap-mode-und -sich anpassendes Design/

Für IEMobile und IE SnapMode (IE10 & 11) müssen Sie also dynamisch eine Inline <style> in <head> mit etwas einfügen.

<script>
 var s = document.createElement('style');
 s.appendChild(document.createTextNode('@-ms-viewport{width:'+width+'px')+';}'));
 document.head.appendChild(s);
</script>

Und leider hat Firefox auch keine: Der Viewport ist ein für alle Mal eingestellt, wie die obige Kompatibilitätstabelle zeigt. In Ermangelung anderer Methoden ist die Verwendung von CSS-Transformation (wie @imcg darauf hingewiesen) die einzige Möglichkeit, den Darstellungsbereich in FireFox Mobile unter Android oder Gecko OS zu ändern. Ich habe es gerade getestet und es funktioniert im Rahmen eines Designs mit fester Größe. (Im "Responsive Design-Kontext" kann das Layout über CSS-Transformation größer skaliert werden, z. B. bei der Desktopgröße eines Telefons, Firefox liest jedoch immer noch die MQs der Telefongröße. Daher muss im RWD-Kontext etwas beachtet werden. Abgesehen vom Webkit )

Allerdings habe ich bei CSSTransform auf Android einige zufällige Abstürze des Webkits festgestellt, daher würde ich die Viewport-Methode für Safari/Chrome/Opera als zuverlässiger empfehlen.

Um die Browserübergreifend-Zuverlässigkeit für die Breite des Darstellungsbereichs zu erhalten, müssen Sie außerdem die Gesamtinkonsistenz zwischen den Browsern für innerWidth in Beziehung setzen/beheben (beachten Sie, dass documentElement.clientWidth viel zuverlässiger ist, um die genaue Breite des Layoutpixels zu erreichen innerWidth) und Sie müssen auch mit devicePixelRatio Abweichungen umgehen, wie in der Tabelle quirksmode.org angegeben.

Update: Nach einigem Nachdenken über eine Lösung für mein eigenes Problem mit Firefox habe ich gerade einen Weg gefunden, den Viewport in Firefox Mobile mit Hilfe von document.write() außer Kraft zu setzen, und zwar nur einmal:

document.write('<meta name="viewport" content="width='+width+'px,initial-scale='+scale+'">');

Ich habe dies gerade in Webkit und Firefox erfolgreich getestet, ohne Probleme beim Zoomen. Ich kann nicht mit Window Phones testen, daher bin ich nicht sicher, ob es document.write für IEMobile funktioniert ...

8
hexalys

Ich weiß, dass dies zwei Jahre zu spät ist, aber ich habe viel Zeit damit verbracht, an diesem Problem zu arbeiten und möchte meine Lösung mitteilen. Ich fand die ursprüngliche Frage sehr hilfreich, und deshalb habe ich das Gefühl, diese Antwort zu veröffentlichen, ist meine Art, etwas zurückzugeben. Meine Lösung funktioniert auf einem iPhone6 ​​und einem 7 "Galaxy Tab. Ich weiß nicht, wie es auf anderen Geräten aussieht, aber ich denke, es sollte sich hauptsächlich verhalten.

Ich habe die Viewport-Logik in eine externe Datei aufgeteilt, so dass sie leicht wiederverwendet werden kann. Zunächst einmal, wie Sie den Code verwenden würden:

<HTML>
<HEAD>    
  <SCRIPT type="text/javascript" src="AutoViewport.js"></SCRIPT>
</HEAD>
<BODY>
  <SCRIPT>
  AutoViewport.setDimensions(yourNeededWidth, yourNeededHeight);
  </SCRIPT>
  <!-- The rest of your HTML goes here -->
</BODY>
</HTML>

Tatsächlich füllte ich meine gewünschte Breite und Höhe um einen kleinen Betrag (etwa 15 Pixel) auf, so dass mein beabsichtigtes Display schön gerahmt wurde. Beachten Sie auch aus dem Verwendungscode, dass Sie in Ihrem HTML-Code kein Viewport-Tag angeben müssen. Meine Bibliothek erstellt automatisch eine für Sie, falls noch keine vorhanden ist ..__ Hier ist AutoViewport.js:

/** Steven Yang, July 2016
Based on http://stackoverflow.com/questions/21419404/setting-the-viewport-to-scale-to-fit-both-width-and-height , this Javascript code allows you to 
cause the viewport to auto-adjust based on a desired pixel width and height
that must be visible on the screen.

This code has been tested on an iPhone6 and a 7" Samsung Galaxy Tab.
In my case, I have a game with the exact dimensions of 990 x 660.  This
script allows me to make the game render within the screen, regardless 
of whether you are in landscape or portrait mode, and it works even
when you hit refresh or rotate your device.

Please use this code freely.  Credit is appreciated, but not required!
*/

function AutoViewport() {}

AutoViewport.setDimensions = function(requiredWidth, requiredHeight) {

/* Conditionally adds a default viewport tag if it does not already exist. */
var insertViewport = function () {

  // do not create if viewport tag already exists
  if (document.querySelector('meta[name="viewport"]'))
    return;

  var viewPortTag=document.createElement('meta');
  viewPortTag.id="viewport";
  viewPortTag.name = "viewport";
  viewPortTag.content = "width=max-device-width, height=max-device-height,initial-scale=1.0";
  document.getElementsByTagName('head')[0].appendChild(viewPortTag);
};

var isPortraitOrientation = function() {
  switch(window.orientation) {  
  case -90:
  case 90:
  return false;
  }

  return true;
 };

var getDisplayWidth = function() {
  if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
    if (isPortraitOrientation())
      return screen.width;
    else
      return screen.height;
  }

  return screen.width;
}

var getDisplayHeight = function() {
  if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
    if (isPortraitOrientation())
      return screen.height;
    else
      return screen.width;
  }

  // I subtract 180 here to compensate for the address bar.  This is imperfect, but seems to work for my Android tablet using Chrome.
  return screen.height - 180;
}

var adjustViewport = function(requiredWidth, requiredHeight) {

  if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)){

    var actual_height = getDisplayHeight();
    var actual_width = getDisplayWidth();

    var min_width = requiredWidth;
    var min_height = requiredHeight;

    var ratio = Math.min(actual_width / min_width, actual_height / min_height);

    document.querySelector('meta[name="viewport"]').setAttribute('content', 'initial-scale=' + ratio + ', maximum-scale=' + ratio + ', minimum-scale=' + ratio + ', user-scalable=yes, width=' + actual_width);
}    
};

  insertViewport();
  adjustViewport(requiredWidth, requiredHeight);
  window.addEventListener('orientationchange', function() {
    adjustViewport(requiredWidth, requiredHeight);      
  });
};

Wenn Sie meinen Code eng mit dem ursprünglichen Code in der Frage vergleichen, werden Sie einige Unterschiede feststellen. Zum Beispiel verlasse ich mich nie auf die Breite oder Höhe des Ansichtsfensters. Stattdessen verlasse ich mich auf das Bildschirmobjekt. Dies ist wichtig, da sich die Breite und Höhe des Ansichtsfensters beim Aktualisieren Ihrer Seite oder beim Drehen des Bildschirms ändern können. Die Breite und die Höhe des Bildschirms ändern sich jedoch nie. Das nächste, was Sie feststellen werden, ist, dass ich die Überprüfung nicht mache (Verhältnis <1). Beim Aktualisieren oder Drehen des Bildschirms führte diese Prüfung zu Inkonsistenzen, sodass ich sie entfernte. Außerdem habe ich einen Handler für die Bildschirmrotation hinzugefügt. 

Zum Schluss möchte ich mich noch einmal bei der Person bedanken, die diese Frage erstellt hat, weil sie die Grundlagen geschaffen hat. Das hat mir Zeit gespart!

4
Steven

Ersetzen Sie Ihr Ansichtsfenster durch Folgendes:

<META NAME="viewport" CONTENT="width=device-width, height=device-height, initial-scale=1, user-scalable=no"/>

Das user-scalable = 0 soll hier die Arbeit für Sie erledigen.

Dies sollte für Sie funktionieren. Wenn es immer noch nicht funktioniert, müssen wir das Ansichtsfenster erweitern. Ersetzen Sie also Ihr Ansichtsfenster und fügen Sie Folgendes hinzu: 

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, target-densitydpi=medium-dpi, user-scalable=0" />

Für Ihren Javascript-Fehler schauen Sie sich diesen Link an:

skalieren Sie den mobilen Webinhalt mithilfe von Viewport-Meta-Tag

3
user3274745

Wenn Sie durch Ändern des Viewport-Meta-Tags kein konsistentes Verhalten über mehrere Geräte erhalten können, können Sie die Größe mit CSS3-Transformationen ändern, ohne die Abmessungen zu ändern:

if (ratio < 1) {
    var box = document.getElementsByTagName('div')[0];
    box.style.webkitTransform = 'scale('+ratio+')';
    box.style.webkitTransformOrigin = '0 0';
}

console.log(box.offsetWidth); // always original width
console.log(box.getBoundingClientRect().width); // new width with scaling applied

Hinweis: Ich habe hier keine Herstellerpräfixe außer Webkit weggelassen, um es einfach zu halten.

Um das skalierte Div zu zentrieren, können Sie die Übersetzungsformen verwenden:

var x = (actual_width - min_width * ratio) / 2;
var y = (actual_height - min_height * ratio) / 2;
box.style.webkitTransform = 'translateX('+x+'px) translateY('+y+'px) scale('+ratio+')';
box.style.webkitTransformOrigin = '0 0';
2
imcg

Ich denke, Steven sollte die akzeptierte Antwort sein.

Wenn es jemandem hilft, würde ich Steven's AutoViewport.js die folgenden zwei Dinge hinzufügen, um die Ansicht innerhalb des Ansichtsfensters zu zentrieren, wenn sich der Benutzer im Querformat befindet: 

Fügen Sie "var viewport_margin = 0;" hinzu. als erste Codezeile (als eigene Zeile vor "function AutoViewport () {}").

Fügen Sie "viewport_margin = Math.abs (actual_width- (ratio * requiredWidth))/(actual_width * 2) * 100 hinzu." Nach der Zeile, die lautet "document.querySelector ('meta [name =" viewport "]'). setAttribute ('content', 'initial-scale =' + ratio + ', maximum-scale =' + ratio + ', minimum -scale = '+ ratio +', vom Benutzer skalierbar = ja, width = '+ actual_width); "

Vielen Dank für alle, die diese Lösung veröffentlicht haben.

UPDATE: In Android scheinen meine Ergänzungen nur mit API 24+ zu funktionieren. Nicht sicher, warum sie nicht mit den APIs 19-23 arbeiten. Irgendwelche Ideen?

0
Strongdog

Setzen Sie die Höhe und Breite der übergeordneten Elemente des Div (html und body) auf 100% und setzen Sie den Rand auf Null.

html, body {
  margin: 0;
  height: 100%;
  width: 100%;
}

Da Sie einen Rand für das div festlegen möchten, müssen Sie beim Festlegen der Breite/Höhe des Elements sicherstellen, dass die Randbreite eingeschlossen wird. Verwenden Sie box-sizing: border-box für das div.

Da Sie einen oberen Rand von 3px für die div-Position wünschen, wird die relative Positionierung des div zu einer Höhe, die 3px zu groß ist. Um dies zu beheben, verwenden Sie die absolute Positionierung auf div und setzen Sie oben, links und unten auf 0.

div {
  position: absolute;
  top: 3px;
  left: 0;
  bottom: 0;
  box-sizing: border-box;
  width: 100%;
  border: 1px solid #f00;
  background-color: #fdd;
}

Hier ist ein Arbeitsbeispiel .

UPDATE: Ich glaube, ich habe die Frage falsch verstanden. Hier ist ein Beispielcode, der den "Zoom" abhängig vom Ansichtsfenster des Geräts anpasst

http://jpanagsagan.com/viewport/index2.html

Beachten Sie, dass ich Jquery verwendet habe, um das Meta-Tag anzufügen, da bei der Verwendung des Vanilla-Anhängens ein Problem aufgetreten ist.

Eines ist mir aufgefallen, dass das Dokument die Korrektur nicht anwendet, wenn Sie im HTML-Code hartcodiert und über JS geändert haben (Überprüfung erforderlich). Ich konnte es über JS ändern, wenn im HTML kein vorheriges Tag vorhanden ist, also habe ich append verwendet.

Sie können mit dem Verhältnis herumspielen, aber in dem Beispiel habe ich die Breite des Ansichtsfensters geteilt durch die Breite des divs verwendet. 

hoffe das hilft.

0
Scott Bartell

UPDATE: Ich glaube, ich habe die Frage falsch verstanden. Hier ist ein Beispielcode, der den "Zoom" abhängig vom Ansichtsfenster des Geräts anpasst

http://jpanagsagan.com/viewport/index2.html

Beachten Sie, dass ich Jquery verwendet habe, um das Meta-Tag anzufügen, da bei der Verwendung des Vanilla-Anhängens ein Problem aufgetreten ist.

Eines ist mir aufgefallen, dass das Dokument die Korrektur nicht anwendet, wenn Sie im HTML-Code hartcodiert und über JS geändert haben (Überprüfung erforderlich). Ich konnte es über JS ändern, wenn im HTML kein vorheriges Tag vorhanden ist, also habe ich append verwendet.

Sie können mit dem Verhältnis herumspielen, aber in dem Beispiel habe ich die Breite des Ansichtsfensters geteilt durch die Breite des divs verwendet. 

hoffe das hilft.

0
Dan1121