Est-il possible de détecter, à l'aide de JavaScript, lorsque l'utilisateur modifie le zoom d'une page? Je veux simplement attraper un événement "zoom" et y répondre (similaire à l'événement window.onresize).
Merci.
Est-il possible de détecter, à l'aide de JavaScript, lorsque l'utilisateur modifie le zoom d'une page? Je veux simplement attraper un événement "zoom" et y répondre (similaire à l'événement window.onresize).
Merci.
Réponses:
Il n'y a aucun moyen de détecter activement s'il y a un zoom. J'ai trouvé une bonne entrée ici sur la façon dont vous pouvez essayer de l'implémenter.
J'ai trouvé deux façons de détecter le niveau de zoom. Une façon de détecter les changements de niveau de zoom repose sur le fait que les valeurs de pourcentage ne sont pas agrandies. Une valeur de pourcentage est relative à la largeur de la fenêtre et n'est donc pas affectée par le zoom de la page. Si vous insérez deux éléments, l'un avec une position en pourcentages et l'autre avec la même position en pixels, ils s'écarteront lorsque la page sera agrandie. Trouvez le rapport entre les positions des deux éléments et vous avez le niveau de zoom. Voir le cas de test. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
Vous pouvez également le faire en utilisant les outils de l'article ci-dessus. Le problème est que vous faites plus ou moins des suppositions éclairées pour savoir si la page a zoomé ou non. Cela fonctionnera mieux dans certains navigateurs que dans d'autres.
Il n'y a aucun moyen de savoir si la page est agrandie s'ils chargent votre page tout en zoomant.
document.body.offsetWidth
J'utilise ce morceau de JavaScript pour réagir aux "événements" de Zoom.
Il interroge la largeur de la fenêtre. (Comme suggéré un peu sur cette page (à laquelle Ian Elliott a lié): http://novemberborn.net/javascript/page-zoom-ff3 [archive] )
Testé avec Chrome, Firefox 3.6 et Opera, pas IE.
Cordialement, 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);
})();
Bonnes nouvelles toutes les personnesquelques personnes! Les navigateurs plus récents déclenchent un événement de redimensionnement de la fenêtre lorsque le zoom est modifié.
Définissons px_ratio comme ci-dessous:
ratio px = ratio du pixel physique au px css.
s'il y a un zoom sur la page, les pixels de la fenêtre (px est différent du pixel) se réduisent et doivent être adaptés à l'écran de sorte que le rapport (pixel physique / CSS_px) doit devenir plus grand.
mais dans le redimensionnement de la fenêtre, la taille de l'écran diminue ainsi que les pixels. donc le ratio se maintiendra.
mais
redimensionnement: déclenche l'événement windows.resize -> ne change pas 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;
}
}
Le point clé est la différence entre CSS PX et Physical Pixel.
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
Cela fonctionne pour moi:
var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);
Il n'est nécessaire que sur IE8. Tous les autres navigateurs génèrent naturellement un événement de redimensionnement.
Il existe un plugin astucieux yonran
qui peut faire la détection. Voici son déjà répondu à la question sur StackOverflow. Cela fonctionne pour la plupart des navigateurs. L'application est aussi simple que ceci:
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
bouton dans l'option Accessibilité. La démo ne réagira pas au changement.
Je voudrais suggérer une amélioration de la solution précédente avec le suivi des modifications de la largeur de la fenêtre. Au lieu de conserver votre propre tableau d'écouteurs d'événements, vous pouvez utiliser le système d'événements javascript existant et déclencher votre propre événement lors d'un changement de largeur, et y lier des gestionnaires d'événements.
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Throttle / debounce peut aider à réduire le taux d'appels de votre gestionnaire.
Vous pouvez également obtenir les événements de redimensionnement du texte et le facteur de zoom en injectant un div contenant au moins un espace insécable (éventuellement masqué) et en vérifiant régulièrement sa hauteur. Si la hauteur change, la taille du texte a changé (et vous savez à quel point - cela se déclenche également, d'ailleurs, si la fenêtre est agrandie en mode pleine page, et vous obtiendrez toujours le facteur de zoom correct, avec la même hauteur / rapport de hauteur).
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
Sur iOS 10, il est possible d'ajouter un écouteur d'événement à l' touchmove
événement et de détecter si la page est agrandie avec l'événement en cours.
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;
});
Bien qu'il s'agisse d'une question vieille de 9 ans, le problème persiste!
J'ai détecté le redimensionnement tout en excluant le zoom dans un projet, j'ai donc modifié mon code pour le faire fonctionner pour détecter à la fois le redimensionnement et le zoom exclusifs l'un de l'autre. Cela fonctionne la plupart du temps, donc si la plupart sont assez bons pour votre projet, cela devrait être utile! Il détecte le zoom à 100% du temps dans ce que j'ai testé jusqu'à présent. Le seul problème est que si l'utilisateur devient fou (c'est-à-dire redimensionner spastiquement la fenêtre) ou si la fenêtre est en retard, il peut se déclencher comme un zoom au lieu d'un redimensionnement de la fenêtre.
Il fonctionne en détectant un changement dans window.outerWidth
ou window.outerHeight
comme redimensionnement de la fenêtre tout en détectant un changement dans window.innerWidth
ou window.innerHeight
indépendamment du redimensionnement de la fenêtre comme 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);
Remarque: Ma solution est comme celle de KajMagnus, mais cela a mieux fonctionné pour moi.
0.05
sans au moins fournir une bonne explication. ;-) Par exemple, je sais que dans Chrome, en particulier, 10% est la plus petite quantité de zoom du navigateur dans tous les cas, mais il n'est pas clair que cela soit vrai pour les autres navigateurs. Pour info, assurez-vous toujours que votre code est testé et soyez prêt à le défendre ou à l'améliorer.
Voici une solution propre:
// 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);
});
L'événement de redimensionnement fonctionne sur les navigateurs modernes en attachant l'événement à window
, puis en lisant les valeurs de body
, ou d'un autre élément avec par exemple ( .getBoundingClientRect () ).
Dans certains navigateurs précédents, il était possible d'enregistrer des gestionnaires d'événements de redimensionnement sur n'importe quel élément HTML. Il est toujours possible de définir des attributs onresize ou d'utiliser addEventListener () pour définir un gestionnaire sur n'importe quel élément. Cependant, les événements de redimensionnement ne sont déclenchés que sur l'objet window (c'est-à-dire retournés par document.defaultView). Seuls les gestionnaires enregistrés sur l'objet window recevront des événements de redimensionnement .
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
Une autre alternative : l'API ResizeObserver
En fonction de votre mise en page, vous pouvez surveiller le redimensionnement d'un élément particulier.
Cela fonctionne bien sur les mises en page «réactives», car la boîte du conteneur est redimensionnée lors du 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>
Veillez à ne pas surcharger les tâches javascript des événements de gestes de l'utilisateur. Utilisez requestAnimationFrame chaque fois que vous avez besoin de rafraîchissements .
Selon MDN, "matchMedia" est le bon moyen de le faire https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
c'est un peu capricieux car chaque instance ne peut regarder qu'un seul MQ à la fois, donc si vous êtes intéressé par un changement de niveau de zoom, vous devez faire un tas de matchers ... mais comme le navigateur est chargé d'émettre les événements, c'est probablement encore plus performant que l'interrogation, et vous pouvez ralentir ou annuler le rappel ou l'épingler à une image d'animation ou quelque chose comme ça - voici une implémentation qui semble assez rapide, n'hésitez pas à échanger _throttle ou autre chose si vous en dépendez déjà.
Exécutez l'extrait de code et effectuez un zoom avant et arrière dans votre navigateur, notez la valeur mise à jour dans le balisage - je n'ai testé cela que dans Firefox! laissez-moi savoir si vous voyez des problèmes.
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>
Je réponds à un lien vieux de 3 ans mais je suppose que voici une réponse plus acceptable,
Créez un fichier .css en tant que,
@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}
PAR EXEMPLE:-
@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}
Le code ci-dessus rend la taille de la police «10px» lorsque l'écran est agrandi à environ 125%. Vous pouvez vérifier les différents niveaux de zoom en modifiant la valeur de «1000px».
max-width
et le taux de zoom?