¿Es posible detectar, usando JavaScript, cuando el usuario cambia el zoom en una página? Simplemente quiero ver un evento de "zoom" y responder a él (similar al evento window.onresize).
Gracias.
¿Es posible detectar, usando JavaScript, cuando el usuario cambia el zoom en una página? Simplemente quiero ver un evento de "zoom" y responder a él (similar al evento window.onresize).
Gracias.
Respuestas:
No hay forma de detectar activamente si hay un zoom. Encontré una buena entrada aquí sobre cómo puede intentar implementarlo.
He encontrado dos formas de detectar el nivel de zoom. Una forma de detectar cambios en el nivel de zoom se basa en el hecho de que los valores porcentuales no se amplían. Un valor porcentual es relativo al ancho de la vista y, por lo tanto, no se ve afectado por el zoom de la página. Si inserta dos elementos, uno con una posición en porcentajes y otro con la misma posición en píxeles, se separarán cuando se amplíe la página. Encuentre la relación entre las posiciones de ambos elementos y obtendrá el nivel de zoom. Ver caso de prueba. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
También puedes hacerlo usando las herramientas de la publicación anterior. El problema es que estás más o menos haciendo conjeturas informadas sobre si la página se ha ampliado o no. Esto funcionará mejor en algunos navegadores que en otros.
No hay forma de saber si la página está ampliada si la cargan mientras está ampliada.
document.body.offsetWidth
Estoy usando este fragmento de JavaScript para reaccionar a los "eventos" de Zoom.
Sondea el ancho de la ventana. (Como se sugiere en esta página (que Ian Elliott enlazó): http://novemberborn.net/javascript/page-zoom-ff3 [archivo] )
Probado con Chrome, Firefox 3.6 y Opera, no IE.
Saludos, Magnus
var zoomListeners = [];
(function(){
// Poll the pixel width of the window; invoke zoom listeners
// if the width has been changed.
var lastWidth = 0;
function pollZoomFireEvent() {
var widthNow = jQuery(window).width();
if (lastWidth == widthNow) return;
lastWidth = widthNow;
// Length changed, user must have zoomed, invoke listeners.
for (i = zoomListeners.length - 1; i >= 0; --i) {
zoomListeners[i]();
}
}
setInterval(pollZoomFireEvent, 100);
})();
Buenas noticias todo el mundo¡algunas personas! Los navegadores más nuevos activarán un evento de cambio de tamaño de ventana cuando se cambie el zoom.
Vamos a definir px_ratio de la siguiente manera:
px px = ratio de píxeles físicos a css px.
si alguno amplía la página, los pxes de la ventana gráfica (px es diferente del píxel) se reducen y deben ajustarse a la pantalla, por lo que la relación (píxel físico / CSS_px) debe aumentar.
pero en el cambio de tamaño de la ventana, se reduce el tamaño de la pantalla y los px entonces la relación se mantendrá.
pero
cambio de tamaño: desencadenar evento windows.resize -> no cambia px_ratio
//for zoom detection
px_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;
$(window).resize(function(){isZooming();});
function isZooming(){
var newPx_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;
if(newPx_ratio != px_ratio){
px_ratio = newPx_ratio;
console.log("zooming");
return true;
}else{
console.log("just resizing");
return false;
}
}
El punto clave es la diferencia entre CSS PX y Physical Pixel.
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
Esto funciona para mi:
var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);
Solo es necesario en IE8. Todos los otros navegadores generan naturalmente un evento de cambio de tamaño.
Hay un ingenioso complemento creado a partir de yonran
eso que puede hacer la detección. Aquí está su pregunta previamente respondida sobre StackOverflow. Funciona para la mayoría de los navegadores. La aplicación es tan simple como esta:
window.onresize = function onresize() {
var r = DetectZoom.ratios();
zoomLevel.innerHTML =
"Zoom level: " + r.zoom +
(r.zoom !== r.devicePxPerCssPx
? "; device to CSS pixel ratio: " + r.devicePxPerCssPx
: "");
}
Always enable zoom
botón en la opción Accesibilidad. La demostración no reaccionará al cambio.
Me gustaría sugerir una mejora a la solución anterior con el seguimiento de los cambios en el ancho de la ventana. En lugar de mantener su propia variedad de oyentes de eventos, puede usar el sistema de eventos javascript existente y activar su propio evento al cambiar el ancho, y vincular los controladores de eventos.
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Acelerador / rebote puede ayudar a reducir la tasa de llamadas de su controlador.
También puede obtener los eventos de cambio de tamaño del texto y el factor de zoom inyectando un div que contenga al menos un espacio no rompible (posiblemente, oculto) y verificando regularmente su altura. Si la altura cambia, el tamaño del texto ha cambiado (y usted sabe cuánto, esto también se dispara, por cierto, si la ventana se amplía en modo de página completa, y aún obtendrá el factor de zoom correcto, con la misma altura / relación de altura).
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
En iOS 10 es posible agregar un detector de touchmove
eventos al evento y detectar, si la página está ampliada con el evento actual.
var prevZoomFactorX;
var prevZoomFactorY;
element.addEventListener("touchmove", (ev) => {
let zoomFactorX = document.documentElement.clientWidth / window.innerWidth;
let zoomFactorY = document.documentElement.clientHeight / window.innerHeight;
let pageHasZoom = !(zoomFactorX === 1 && zoomFactorY === 1);
if(pageHasZoom) {
// page is zoomed
if(zoomFactorX !== prevZoomFactorX || zoomFactorY !== prevZoomFactorY) {
// page is zoomed with this event
}
}
prevZoomFactorX = zoomFactorX;
prevZoomFactorY = zoomFactorY;
});
Aunque esta es una pregunta de 9 años, ¡el problema persiste!
He estado detectando el cambio de tamaño al excluir el zoom en un proyecto, por lo que edité mi código para que funcione para detectar tanto el cambio de tamaño como el zoom exclusivos entre sí. Funciona la mayor parte del tiempo, por lo que si la mayoría es lo suficientemente bueno para su proyecto, ¡esto debería ser útil! Detecta el zoom el 100% del tiempo en lo que he probado hasta ahora. El único problema es que si el usuario se vuelve loco (es decir, si cambia el tamaño de la ventana de forma espasmódica) o si la ventana se retrasa, puede activarse como un zoom en lugar de un cambio de tamaño de la ventana.
Funciona mediante la detección de un cambio en el tamaño de la ventana window.outerWidth
o window.outerHeight
al cambiar el tamaño de la ventana, mientras que detecta un cambio en el tamaño de la ventana window.innerWidth
o window.innerHeight
independiente del mismo como un zoom.
//init object to store window properties
var windowSize = {
w: window.outerWidth,
h: window.outerHeight,
iw: window.innerWidth,
ih: window.innerHeight
};
window.addEventListener("resize", function() {
//if window resizes
if (window.outerWidth !== windowSize.w || window.outerHeight !== windowSize.h) {
windowSize.w = window.outerWidth; // update object with current window properties
windowSize.h = window.outerHeight;
windowSize.iw = window.innerWidth;
windowSize.ih = window.innerHeight;
console.log("you're resizing"); //output
}
//if the window doesn't resize but the content inside does by + or - 5%
else if (window.innerWidth + window.innerWidth * .05 < windowSize.iw ||
window.innerWidth - window.innerWidth * .05 > windowSize.iw) {
console.log("you're zooming")
windowSize.iw = window.innerWidth;
}
}, false);
Nota: Mi solución es como la de KajMagnus, pero me ha funcionado mejor.
0.05
por lo menos, sin dar una buena explicación. ;-) Por ejemplo, sé que en Chrome, específicamente, el 10% es la cantidad más pequeña que el navegador ampliará en cualquier caso, pero no está claro que esto sea cierto para otros navegadores. Para tu información, asegúrate siempre de que tu código esté probado y prepárate para defenderlo o mejorarlo.
Aquí hay una solución limpia:
// polyfill window.devicePixelRatio for IE
if(!window.devicePixelRatio){
Object.defineProperty(window,'devicePixelRatio',{
enumerable: true,
configurable: true,
get:function(){
return screen.deviceXDPI/screen.logicalXDPI;
}
});
}
var oldValue=window.devicePixelRatio;
window.addEventListener('resize',function(e){
var newValue=window.devicePixelRatio;
if(newValue!==oldValue){
// TODO polyfill CustomEvent for IE
var event=new CustomEvent('devicepixelratiochange');
event.oldValue=oldValue;
event.newValue=newValue;
oldValue=newValue;
window.dispatchEvent(event);
}
});
window.addEventListener('devicepixelratiochange',function(e){
console.log('devicePixelRatio changed from '+e.oldValue+' to '+e.newValue);
});
El evento de cambio de tamaño funciona en los navegadores modernos al adjuntar el evento window
y luego leer los valores del body
u otro elemento con, por ejemplo ( .getBoundingClientRect () ).
En algunos navegadores anteriores, era posible registrar controladores de eventos de cambio de tamaño en cualquier elemento HTML. Todavía es posible establecer atributos onresize o usar addEventListener () para establecer un controlador en cualquier elemento. Sin embargo, los eventos de cambio de tamaño solo se activan en el objeto de la ventana (es decir, devuelto por document.defaultView). Solo los controladores registrados en el objeto de la ventana recibirán eventos de cambio de tamaño .
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
Otra alternativa : la API ResizeObserver
Dependiendo de su diseño, puede mirar para cambiar el tamaño de un elemento en particular.
Esto funciona bien en diseños "receptivos", porque la caja del contenedor cambia de tamaño al hacer zoom.
function watchBoxchange(e){
// console.log(e[0].contentBoxSize.inlineSize+" "+e[0].contentBoxSize.blockSize)
info.textContent = e[0].contentBoxSize.inlineSize+" * "+e[0].contentBoxSize.blockSize + "px"
}
new ResizeObserver(watchBoxchange).observe(fluid)
#fluid {
width: 200px;
height:100px;
overflow: auto;
resize: both;
border: 3px black solid;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 8vh
}
<div id="fluid">
<info id="info"></info>
</div>
Tenga cuidado de no sobrecargar las tareas de JavaScript de los eventos de gestos del usuario. Use requestAnimationFrame cuando necesite redibujar.
Según MDN, "matchMedia" es la forma correcta de hacer esto https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
es un poco complicado porque cada instancia solo puede ver un MQ a la vez, por lo que si está interesado en cualquier cambio en el nivel de zoom, debe hacer un montón de coincidencias ... pero dado que el navegador se encarga de emitir los eventos, probablemente sea aún más eficiente que el sondeo, y podría acelerar o cancelar la devolución de llamada o fijarla a un cuadro de animación o algo así; aquí hay una implementación que parece bastante ágil, no dude en intercambiar _ acelerador o lo que sea si ya depende de eso.
Ejecute el fragmento de código y amplíe y reduzca en su navegador, observe el valor actualizado en el marcado: ¡solo lo probé en Firefox! déjame saber si ves algún problema.
const el = document.querySelector('#dppx')
if ('matchMedia' in window) {
function observeZoom(cb, opts) {
opts = {
// first pass for defaults - range and granularity to capture all the zoom levels in desktop firefox
ceiling: 3,
floor: 0.3,
granularity: 0.05,
...opts
}
const precision = `${opts.granularity}`.split('.')[1].length
let val = opts.floor
const vals = []
while (val <= opts.ceiling) {
vals.push(val)
val = parseFloat((val + opts.granularity).toFixed(precision))
}
// construct a number of mediamatchers and assign CB to all of them
const mqls = vals.map(v => matchMedia(`(min-resolution: ${v}dppx)`))
// poor person's throttle
const throttle = 3
let last = performance.now()
mqls.forEach(mql => mql.addListener(function() {
console.debug(this, arguments)
const now = performance.now()
if (now - last > throttle) {
cb()
last = now
}
}))
}
observeZoom(function() {
el.innerText = window.devicePixelRatio
})
} else {
el.innerText = 'unable to observe zoom level changes, matchMedia is not supported'
}
<div id='dppx'>--</div>
Estoy respondiendo a un enlace de 3 años pero creo que aquí hay una respuesta más aceptable,
Crear archivo .css como
@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}
P.EJ:-
@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}
El código anterior hace que el tamaño de la fuente '10px' cuando la pantalla se amplía a aproximadamente 125%. Puede verificar diferentes niveles de zoom cambiando el valor de '1000px'.
max-width
y la relación de zoom?