É possível detectar, usando JavaScript, quando o usuário altera o zoom em uma página? Eu simplesmente quero pegar um evento "zoom" e responder a ele (semelhante ao evento window.onresize).
Obrigado.
É possível detectar, usando JavaScript, quando o usuário altera o zoom em uma página? Eu simplesmente quero pegar um evento "zoom" e responder a ele (semelhante ao evento window.onresize).
Obrigado.
Respostas:
Não há como detectar ativamente se há um zoom. Encontrei uma boa entrada aqui sobre como você pode tentar implementá-lo.
Eu encontrei duas maneiras de detectar o nível de zoom. Uma maneira de detectar alterações no nível de zoom depende do fato de que os valores percentuais não são ampliados. Um valor percentual é relativo à largura da janela de exibição e, portanto, não é afetado pelo zoom da página. Se você inserir dois elementos, um com posição em porcentagem e outro com a mesma posição em pixels, eles se afastarão quando a página for ampliada. Encontre a proporção entre as posições dos dois elementos e você terá o nível de zoom. Veja o caso de teste. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
Você também pode fazer isso usando as ferramentas da postagem acima. O problema é que você está mais ou menos tentando adivinhar se a página foi ou não ampliada. Isso funcionará melhor em alguns navegadores do que em outros.
Não há como saber se a página está com zoom, se eles carregam sua página enquanto estiver com zoom.
document.body.offsetWidth
Estou usando este pedaço de JavaScript para reagir aos "eventos" do Zoom.
Ele examina a largura da janela. (Como sugerido nesta página (ao qual Ian Elliott se vinculou): http://novemberborn.net/javascript/page-zoom-ff3 [arquivo] )
Testado com Chrome, Firefox 3.6 e Opera, não com o IE.
Atenciosamente, 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);
})();
Boas notícias todosalgumas pessoas! Navegadores mais recentes acionarão um evento de redimensionamento de janela quando o zoom for alterado.
Vamos definir px_ratio como abaixo:
relação do px = relação do pixel físico ao css px.
se houver um zoom na página, os pixels da janela de visualização (o px é diferente do pixel) são reduzidos e devem ser ajustados à tela para que a proporção (pixel físico / CSS_px) seja maior.
mas no redimensionamento da janela, o tamanho da tela também reduz os pixels. então a proporção será mantida.
mas
redimensionar: acionar evento windows.resize -> não altera 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;
}
}
O ponto principal é a diferença entre CSS PX e Physical Pixel.
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
Isso funciona para mim:
var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);
Só é necessário no IE8. Todos os outros navegadores geram naturalmente um evento de redimensionamento.
Existe um plugin bacana construído a partir dele yonran
que pode fazer a detecção. Aqui está sua pergunta respondida anteriormente no StackOverflow. Funciona para a maioria dos navegadores. A aplicação é tão simples 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ão na opção Acessibilidade. A demonstração não reagirá à mudança.
Gostaria de sugerir uma melhoria para a solução anterior com o rastreamento de alterações na largura da janela. Em vez de manter sua própria matriz de ouvintes de eventos, você pode usar o sistema de eventos javascript existente e acionar seu próprio evento após a alteração da largura e vincular manipuladores de eventos a ele.
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
A aceleração / rejeição pode ajudar a reduzir a taxa de chamadas de seu manipulador.
Você também pode obter os eventos de redimensionamento de texto e o fator de zoom injetando uma div contendo pelo menos um espaço que não pode ser quebrado (possivelmente oculto) e verificando regularmente sua altura. Se a altura mudar, o tamanho do texto foi alterado (e você sabe quanto - isso também dispara, aliás, se a janela for ampliada no modo de página inteira e você ainda obterá o fator de zoom correto, com a mesma altura / relação altura).
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
No iOS 10, é possível adicionar um ouvinte de touchmove
evento ao evento e detectar se a página é ampliada com o evento atual.
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;
});
Embora essa seja uma pergunta antiga de 9 anos, o problema persiste!
Eu tenho detectado o redimensionamento e excluído o zoom em um projeto. Por isso, editei meu código para fazê-lo funcionar para detectar o redimensionamento e o zoom exclusivos um do outro. Funciona na maioria das vezes, portanto, se a maioria é boa o suficiente para o seu projeto, isso deve ser útil! Ele detecta o zoom 100% do tempo no que testei até agora. O único problema é que, se o usuário ficar louco (ou seja, redimensionar espasticamente a janela) ou se a janela ficar lenta, poderá disparar como um zoom em vez de redimensionar a janela.
Ele funciona detectando uma alteração no redimensionamento de uma janela window.outerWidth
ou window.outerHeight
ao mesmo tempo em que detecta uma alteração window.innerWidth
ou window.innerHeight
um redimensionamento independente da janela como um 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: Minha solução é como a do KajMagnus, mas isso funcionou melhor para mim.
0.05
sem pelo menos fornecer uma boa explicação. ;-) Por exemplo, eu sei que no Chrome, especificamente, 10% é a menor quantidade que o navegador ampliará em qualquer caso, mas não está claro se isso é verdade para outros navegadores. fyi, sempre verifique se seu código foi testado e esteja preparado para defendê-lo ou melhorá-lo.
Aqui está uma solução limpa:
// 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);
});
O evento redimensionar funciona em navegadores modernos, anexando o evento window
e lendo os valores do body
ou de outro elemento com, por exemplo ( .getBoundingClientRect () ).
Em alguns navegadores anteriores, era possível registrar redimensionadores de manipuladores de eventos em qualquer elemento HTML. Ainda é possível definir atributos de redimensionamento ou usar addEventListener () para definir um manipulador em qualquer elemento. No entanto, os eventos de redimensionamento são acionados apenas no objeto da janela (ou seja, retornados por document.defaultView). Somente manipuladores registrados no objeto de janela receberão eventos de redimensionamento .
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
Outra alternativa : a API ResizeObserver
Dependendo do layout, você pode assistir ao redimensionamento de um elemento específico.
Isso funciona bem em layouts «responsivos», porque a caixa do contêiner é redimensionada ao aplicar 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>
Cuidado para não sobrecarregar tarefas javascript dos eventos de gestos do usuário. Use requestAnimationFrame sempre que precisar redesenhar.
De acordo com a MDN, "matchMedia" é a maneira correta de fazer isso https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
é um pouco complicado, porque cada instância pode assistir apenas um MQ de cada vez, por isso, se você estiver interessado em qualquer alteração no nível de zoom, precisará fazer vários matchers .. mas como o navegador é responsável por emitir os eventos, provavelmente ainda mais eficiente que a pesquisa, e você pode limitar ou rejeitar o retorno de chamada ou fixá-lo em um quadro de animação ou algo assim - aqui está uma implementação que parece bastante rápida, sinta-se à vontade para trocar de acelerador ou qualquer outra coisa, se você já depende disso.
Execute o trecho de código e aumente e diminua o zoom no seu navegador, observe o valor atualizado na marcação - só testei isso no Firefox! deixe-me saber se você vê algum 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>
Estou respondendo a um link de 3 anos, mas acho que aqui está uma resposta mais aceitável,
Crie o arquivo .css como,
@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}
POR EXEMPLO:-
@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}
O código acima torna o tamanho da fonte '10px' quando a tela é ampliada para aproximadamente 125%. Você pode verificar diferentes níveis de zoom alterando o valor de '1000px'.
max-width
e a taxa de zoom?