javascript - sacar - ¿Cómo reinicio la escala/el zoom de una aplicación web en un cambio de orientación en el iPhone?
la pantalla de mi iphone se puso grande (11)
Cuando inicio mi aplicación en modo retrato, funciona bien. Luego giro en el paisaje y se amplía. Para que se escale correctamente para el modo paisaje, tengo que tocar dos veces dos veces, primero para acercarme por completo (el comportamiento normal de doble toque) y nuevamente para alejar todo (otra vez, el comportamiento normal de doble toque) . Cuando se aleja, se aleja a la escala NUEVA correcta para el modo horizontal.
Volver a ver el retrato parece funcionar de manera más consistente; es decir, maneja el zoom para que la escala sea correcta cuando la orientación cambia de nuevo a retrato.
Estoy tratando de averiguar si esto es un error? o si esto es algo que se puede arreglar con JavaScript?
Con el meta contenido de la ventana gráfica, estoy configurando la escala inicial en 1.0 y NO estoy configurando la escala mínima o máxima (ni quiero hacerlo). Estoy configurando el ancho para el ancho del dispositivo.
¿Algunas ideas? Sé que mucha gente estaría agradecida de tener una solución, ya que parece ser un problema persistente.
Aquí hay otra forma de hacerlo, que parece funcionar bien.
Establezca la metaetiqueta para restringir la ventana gráfica a scale = 1, lo que evita el zoom:
<meta name = "viewport" content = "width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1">
Con javascript, cambie la metaetiqueta 1/2 segundo más tarde para permitir el zoom:
setTimeout (function () {document.querySelector ("meta [name = viewport]"). setAttribute (''contenido'', ''ancho = dispositivo-ancho, escala inicial = 1'');}, 500);
De nuevo con javascript, en el cambio de orientación, vuelva a cargar la página:
window.onorientationchange = function () {window.location.reload ();};
Cada vez que reoriente el dispositivo, la página se recarga, inicialmente sin zoom. Pero 1/2 segundo después, se restaura la capacidad de zoom.
Creé una demostración funcional de un diseño de paisaje / retrato, pero el zoom debe estar desactivado para que funcione sin JavaScript:
http://matthewjamestaylor.com/blog/ipad-layout-with-landscape-portrait-modes
Elisabeth puede cambiar el contenido de la vista dinámicamente agregando la propiedad "id" a la metaetiqueta:
<meta name="viewport" id="view" content="user-scalable=yes, width=device-width minimum-scale=1, maximum-scale=1" />
Entonces solo puedes llamar por javascript:
document.getElementById("view").setAttribute(''content'',''user-scalable=yes, width=device-width, minimum-scale=1, maximum-scale=10'');
Encontré una solución implementada muy fácilmente. Establezca el foco en un elemento de texto que tenga un tamaño de fuente de 50 px al completar el formulario. No parece funcionar si el elemento de texto está oculto, pero ocultar este elemento se realiza fácilmente al establecer las propiedades de color de los elementos para que no tengan opacidad.
He encontrado una nueva solución, diferente de cualquier otra que he visto, al deshabilitar el zoom nativo de iOS, y en su lugar implementar la funcionalidad de zoom en JavaScript.
Una excelente experiencia en las otras soluciones para el problema de zoom / orientación es de Sérgio Lopes: una solución para el famoso error de zoom de iOS en la orientación cambiar a retrato .
<!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://.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>
Se podría mejorar, pero para mis necesidades evita los principales inconvenientes que ocurren con todas las otras soluciones que he visto. Hasta ahora solo lo he probado usando Safari móvil en un iPad 2 con iOS4.
El enfoque () / desenfoque () es una solución para evitar el bloqueo ocasional de la funcionalidad de zoom que puede ocurrir después de cambiar la orientación y el zoom varias veces.
Al establecer document.body.style, se fuerza un repintado de pantalla completa, lo que evita ocasionalmente problemas intermitentes en los que el repintado falla gravemente después del zoom.
He estado usando esta función en mi proyecto.
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;
}
así que solo agregueEventListener:
if( /iPad|iPhone|iPod|Android/i.test(navigator.userAgent) ){
window.addEventListener("orientationchange", function() {
changeViewPort("maximum-scale", 1);
changeViewPort("maximum-scale", 10);
}
}
Jeremy Keith ( @adactio ) tiene una buena solución para esto en su blog Orientación y escala
Mantenga el marcado escalable al no establecer una escala máxima en el marcado.
<meta name="viewport" content="width=device-width, initial-scale=1">
A continuación, deshabilite la escalabilidad con javascript en carga hasta que gesturestart cuando permita la escalabilidad de nuevo con este 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);
}
}
Actualización 22-12-2014:
En un iPad 1, esto no funciona, falla en eventlistener. Descubrí que la eliminación de .body
corrige que:
document.addEventListener(''gesturestart'', function() { /* */ });
MobileSafari admite el evento orientationchange
en el objeto de window
. Lamentablemente, no parece haber una manera de controlar directamente el zoom a través de JavaScript. Tal vez podrías escribir / cambiar dinámicamente la meta
que controla la ventana gráfica, pero dudo que eso funcione, solo afecta el estado inicial de la página. Tal vez podrías usar este evento para cambiar el tamaño de tu contenido usando CSS. ¡Buena suerte!
Si tiene el ancho establecido en la ventana gráfica:
<meta name = "viewport" content = "width=device-width; initial-scale=1.0;
maximum-scale=1.0;" />
Y a continuación, cambie la orientación que hará zoom aleatoriamente a veces (especialmente si está arrastrando la pantalla) para solucionar esto, no establezca un ancho aquí que utilicé:
<meta id="viewport" name="viewport" content="initial-scale=1.0; user-scalable=0;
minimum-scale=1.0; maximum-scale=1.0" />
Esto corrige el zoom, pase lo que pase, puede usar window.onorientationchange event o si desea que sea independiente de la plataforma (útil para probar) el método window.innerWidth .
Tuve el mismo problema y establecer la escala máxima = 1.0 me funcionó.
Editar: como se menciona en los comentarios, esto desactiva el zoom del usuario, excepto cuando el contenido excede la resolución de ancho. Como se mencionó, esto podría no ser sabio. También podría ser deseado en algunos casos.
El código de la vista:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;">
Scott Jehl propuso una solución fantástica que utiliza el acelerómetro para anticipar los cambios de orientación. Esta solución es muy sensible y no interfiere con los gestos de zoom.
https://github.com/scottjehl/iOS-Orientationchange-Fix
Cómo funciona: esta solución funciona escuchando el acelerómetro del dispositivo para predecir cuándo va a ocurrir un cambio de orientación. Cuando considera que una orientación cambia inminente, la secuencia de comandos desactiva el zoom del usuario, permitiendo que el cambio de orientación ocurra correctamente, con el zoom desactivado. La secuencia de comandos restaura el zoom una vez que el dispositivo está orientado cerca de la posición vertical o después de que su orientación ha cambiado. De esta forma, el zoom del usuario nunca se deshabilita mientras la página está en uso.
Fuente minificada:
/*! 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);