Comment détecter le niveau de zoom de la page dans tous les navigateurs modernes? Bien que ce thread indique comment faire cela dans IE7 et IE8, je ne trouve pas de bonne solution multi-navigateurs.
Firefox enregistre le niveau de zoom de la page pour un accès ultérieur. Est-ce que je pourrais obtenir le niveau de zoom sur la première page de chargement? Quelque part que j'ai lu, cela fonctionne lorsqu'un changement de zoom se produit après la page est chargée.
Existe-t-il un moyen de piéger l'événement 'zoom'
?
J'ai besoin de cela car certains de mes calculs sont basés sur les pixels et peuvent fluctuer lors d'un zoom.
Exemple modifié donné par @tfl
Cette page alerte différentes valeurs de hauteur lors d’un zoom. [jsFiddle]
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" type="text/javascript"/></script>
</head>
<body>
<div id="xy" style="border:1px solid #f00; width:100px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque sollicitudin tortor in lacus tincidunt volutpat. Integer dignissim imperdiet mollis. Suspendisse quis tortor velit, placerat tempor neque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent bibendum auctor lorem vitae tempor. Nullam condimentum aliquam elementum. Nullam egestas gravida elementum. Maecenas mattis molestie nisl sit amet vehicula. Donec semper tristique blandit. Vestibulum adipiscing placerat mollis.</div>
<button onclick="alert($('#xy').height());">Show</button>
</body>
</html>
Maintenant, le désordre est encore plus grand que lorsque cette question a été posée pour la première fois. En lisant toutes les réponses et les articles de blog que j'ai pu trouver, voici un résumé. J'ai également mis en place cette page pour tester toutes ces méthodes de mesure du niveau de zoom .
Edit (2011-12-12): J'ai ajouté un projet pouvant être cloné: https://github.com/tombigel/detect-zoom
screen.deviceXDPI / screen.logicalXDPI
(ou screen.systemXDPI / screen.logicalXDPI
pour le niveau de zoom par rapport au zoom par défaut)var body = document.body,r = body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth;
(grâce à cet exemple ou cette réponse )screen.width
largeur de l'écran d'interrogation du support (voir ci-dessous) (tire parti du fait que screen.width
utilise des pixels de périphérique mais que MQ width utilise des pixels CSS - grâce à Largeurs de Quirksmode )-webkit-text-size-adjust:none
.document.width / jQuery(document).width()
(merci à Dirk van Oosterbosch ci-dessus ). Pour obtenir le rapport en termes de pixels de périphérique (au lieu de rapport au zoom par défaut), multipliez par window.devicePixelRatio
.parseInt(getComputedStyle(document.documentElement,null).width) / document.documentElement.clientWidth
(from this answer )document.documentElement.offsetWidth
width d'un position:fixed; width:100%
div. à partir de maintenant ( Le tableau des largeurs de Quirksmode indique qu'il s'agit d'un bogue; innerWidth doit correspondre à CSS px). Nous utilisons l'élément position: fixed pour obtenir la largeur de la fenêtre y compris l'espace où se trouvent les barres de défilement}; document.documentElement.clientWidth exclut cette largeur. Ceci est cassé depuis quelque temps en 2011; Je ne sais plus comment obtenir le niveau de zoom dans Opera.Voici une recherche binaire pour Firefox 4, car je ne connais aucune variable où il est exposé:
<style id=binarysearch></style>
<div id=dummyElement>Dummy element to test media queries.</div>
<script>
var mediaQueryMatches = function(property, r) {
var style = document.getElementById('binarysearch');
var dummyElement = document.getElementById('dummyElement');
style.sheet.insertRule('@media (' + property + ':' + r +
') {#dummyElement ' +
'{text-decoration: underline} }', 0);
var matched = getComputedStyle(dummyElement, null).textDecoration
== 'underline';
style.sheet.deleteRule(0);
return matched;
};
var mediaQueryBinarySearch = function(
property, unit, a, b, maxIter, epsilon) {
var mid = (a + b)/2;
if (maxIter == 0 || b - a < epsilon) return mid;
if (mediaQueryMatches(property, mid + unit)) {
return mediaQueryBinarySearch(
property, unit, mid, b, maxIter-1, epsilon);
} else {
return mediaQueryBinarySearch(
property, unit, a, mid, maxIter-1, epsilon);
}
};
var mozDevicePixelRatio = mediaQueryBinarySearch(
'min--moz-device-pixel-ratio', '', a, b, maxIter, epsilon);
var ff35DevicePixelRatio = screen.width / mediaQueryBinarySearch(
'min-device-width', 'px', 0, 6000, 25, .0001);
</script>
Pour moi, pour Chrome/Webkit, document.width / jQuery(document).width()
ne fonctionnait pas. Lorsque j'ai créé une petite fenêtre et que j'ai zoomé sur mon site de manière à ce que des barres de défilement horizontales apparaissent, document.width / jQuery(document).width()
n'était pas égal à 1 au zoom par défaut. En effet, document.width
inclut une partie du document en dehors de la fenêtre d'affichage.
Utiliser window.innerWidth
et window.outerWidth
a fonctionné. Pour une raison quelconque, dans Chrome, outerWidth est mesuré en pixels d'écran et innerWidth en css pixels.
var screenCssPixelRatio = (window.outerWidth - 8) / window.innerWidth;
if (screenCssPixelRatio >= .46 && screenCssPixelRatio <= .54) {
zoomLevel = "-4";
} else if (screenCssPixelRatio <= .64) {
zoomLevel = "-3";
} else if (screenCssPixelRatio <= .76) {
zoomLevel = "-2";
} else if (screenCssPixelRatio <= .92) {
zoomLevel = "-1";
} else if (screenCssPixelRatio <= 1.10) {
zoomLevel = "0";
} else if (screenCssPixelRatio <= 1.32) {
zoomLevel = "1";
} else if (screenCssPixelRatio <= 1.58) {
zoomLevel = "2";
} else if (screenCssPixelRatio <= 1.90) {
zoomLevel = "3";
} else if (screenCssPixelRatio <= 2.28) {
zoomLevel = "4";
} else if (screenCssPixelRatio <= 2.70) {
zoomLevel = "5";
} else {
zoomLevel = "unknown";
}
Tu peux essayer
var browserZoomLevel = Math.round(window.devicePixelRatio * 100);
Cela vous donnera le pourcentage de zoom du navigateur.
Pour attraper un événement de zoom, vous pouvez utiliser
$(window).resize(function() {
// your code
});
Mon collègue et moi avons utilisé le script de https://github.com/tombigel/detect-zoom . En outre, nous avons également créé dynamiquement un élément svg et vérifié sa propriété currentScale. Cela fonctionne très bien sur Chrome et probablement avec la plupart des navigateurs. Sur FF, la fonctionnalité "Zoom uniquement sur le texte" doit être désactivée. SVG est supporté sur la plupart des navigateurs. Au moment de la rédaction de cet article, testé sur IE10, FF19 et Chrome28.
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
svg.setAttribute('version', '1.1');
document.body.appendChild(svg);
var z = svg.currentScale;
... more code ...
document.body.removeChild(svg);
J'ai trouvé cet article extrêmement utile. Grand merci à Yonran. Je souhaitais transmettre certaines connaissances supplémentaires acquises lors de la mise en œuvre de certaines des techniques qu’il avait fournies. Dans FF6 et Chrome 9, la prise en charge des requêtes multimédia de JS a été ajoutée, ce qui peut grandement simplifier l’approche d’interrogation multimédia nécessaire pour déterminer le zoom en FF. Voir la documentation à MDN ici . Pour mes besoins, je devais seulement savoir si le navigateur était agrandi ou réduit, je n'avais pas besoin du facteur de zoom réel. J'ai pu obtenir ma réponse avec une ligne de JavaScript:
var isZoomed = window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;
En combinant cela avec les solutions IE8 + et Webkit, qui étaient également des lignes simples, j'ai été capable de détecter le zoom sur la grande majorité des navigateurs frappant notre application avec seulement quelques lignes de code.
zoom = ( window.outerWidth - 10 ) / window.innerWidth
C'est tout ce dont vous avez besoin.
J'ai une solution pour cela à compter de janvier 2016. Testé dans les navigateurs Chrome, Firefox et MS Edge.
Le principe est le suivant. Collectez 2 points MouseEvent éloignés. Chaque événement de souris est livré avec les coordonnées de l'écran et du document. Mesurer la distance entre les 2 points dans les deux systèmes de coordonnées. Bien qu'il existe des décalages fixes variables entre les systèmes de coordonnées dus au mobilier du navigateur, la distance entre les points doit être identique si la page n'est pas agrandie. La raison pour laquelle vous spécifiez "très éloigné" (je mets 12 pixels) est telle que de petits changements de zoom (par exemple 90% ou 110%) sont détectables.
Référence: https://developer.mozilla.org/en/docs/Web/Events/mousemove
Pas:
Ajouter un auditeur de mouvement de souris
window.addEventListener("mousemove", function(event) {
// handle event
});
Capturez 4 mesures à partir d'événements de souris:
event.clientX, event.clientY, event.screenX, event.screenY
Mesurer la distance d_c entre les 2 points du système client
Mesurer la distance d_s entre les 2 points dans le système d’écran
Si d_c! = D_s, le zoom est appliqué. La différence entre les deux vous indique la quantité de zoom.
N.B. Seuls les calculs de distance sont rarement utilisés, p. Ex. lorsque vous pouvez échantillonner un nouvel événement de souris très éloigné du précédent.
Limitations: Supposons que l'utilisateur bouge la souris au moins un peu et que le zoom est inconnaissable jusqu'à cette heure.
Cela a très bien fonctionné pour les navigateurs Web (Chrome, Safari):
function isZoomed() {
var width, mediaQuery;
width = document.body.clientWidth;
mediaQuery = '(max-width: ' + width + 'px) and (min-width: ' + width + 'px)';
return !window.matchMedia(mediaQuery).matches;
}
Ne semble pas fonctionner dans Firefox cependant.
Cela fonctionne aussi dans WebKit:
var zoomLevel = document.width / document.body.clientWidth;
Dans Internet Explorer 7, 8 et 9, cela fonctionne:
function getZoom() {
var screen;
screen = document.frames.screen;
return ((screen.deviceXDPI / screen.systemXDPI) * 100 + 0.9).toFixed();
}
Le "+0,9" est ajouté pour éviter les erreurs d'arrondi (sinon, vous obtiendriez 104% et 109% lorsque le zoom du navigateur est défini sur 105% et 110% respectivement).
Dans IE6, le zoom n'existe pas, il est donc inutile de vérifier le zoom.
En gros, nous avons:
window.devicePixelRatio
qui prend en compte le zoom * au niveau du navigateur ainsi que le zoom système/la densité de pixels.vw
vh
unités CSSresize
, qui est déclenché lors d'un changement de niveau de zoom, provoque la modification de la taille effective de la fenêtrecela devrait suffire pour _/normal UX. Si vous devez détecter un niveau de zoom, cela peut indiquer une mauvaise conception de l'interface utilisateur.
Pitch-zoom est plus difficile à suivre et n'est pas considéré pour le moment.
Ce que je suis venu avec est:
1) Créez un position:fixed
<div>
avec width:100%
( id = zoomdiv )
2) lors du chargement de la page:
zoomlevel=$("#zoomdiv").width()*1.0 / screen.availWidth
Et cela a fonctionné pour moi pour les zooms ctrl+
et ctrl-
.
ou je peux ajouter la ligne à un événement $(window).onresize()
pour obtenir le niveau de zoom actif
Code:
<script>
var zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;
$(window).resize(function(){
zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;
alert(zoom);
});
</script>
<body>
<div id=zoomdiv style="width:100%;position:fixed;"></div>
</body>
P.S. : ceci est mon premier post, pardonnez les erreurs
Sur les appareils mobile (avec Chrome pour Android ou Opera Mobile), vous pouvez détecter le zoom de window.visualViewport.scale . https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API
Détecter sur Safari: document.documentElement.clientWidth/window.innerWidth (retourne 1 si aucun zoom sur le périphérique).
Sur Chrome
var ratio = (screen.availWidth / document.documentElement.clientWidth);
var zoomLevel = Number(ratio.toFixed(1).replace(".", "") + "0");
Vos calculs sont toujours basés sur un nombre de pixels CSS. Ils sont juste une taille différente sur l'écran maintenant. C'est le point de zoom de la page entière.
Que voudriez-vous que se passe sur un navigateur sur un périphérique 192 ppp qui affiche donc normalement quatre pixels de périphérique pour chaque pixel d'une image? À un zoom de 50%, cet appareil affiche désormais un pixel d'image sur un pixel de périphérique.
Ceci est pour Chrome, à la suite de user800583 answer ...
J'ai passé quelques heures sur ce problème et je n'ai pas trouvé de meilleure approche, mais:
window.outerWidth/window.innerWidth
, et dans le cas contraire, le ratio semble être (window.outerWidth-16)/window.innerWidth
, mais le 1er cas peut être abordé par le second.Alors je suis venu à ce qui suit ...
Mais cette approche a des limites: par exemple, si vous jouez à l’accordéon avec la fenêtre de l’application (agrandissez et réduisez rapidement la largeur de la fenêtre), vous obtiendrez des écarts entre les niveaux de zoom même si le zoom n’a pas changé mis à jour exactement dans le même temps).
var snap = function (r, snaps)
{
var i;
for (i=0; i < 16; i++) { if ( r < snaps[i] ) return i; }
};
var w, l, r;
w = window.outerWidth, l = window.innerWidth;
return snap((w - 16) / l,
[ 0.29, 0.42, 0.58, 0.71, 0.83, 0.95, 1.05, 1.18, 1.38, 1.63, 1.88, 2.25, 2.75, 3.5, 4.5, 100 ],
);
Et si vous voulez le facteur:
var snap = function (r, snaps, ratios)
{
var i;
for (i=0; i < 16; i++) { if ( r < snaps[i] ) return eval(ratios[i]); }
};
var w, l, r;
w = window.outerWidth, l = window.innerWidth;
return snap((w - 16) / l,
[ 0.29, 0.42, 0.58, 0.71, 0.83, 0.95, 1.05, 1.18, 1.38, 1.63, 1.88, 2.25, 2.75, 3.5, 4.5, 100 ],
[ 0.25, '1/3', 0.5, '2/3', 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3, 4, 5 ]
);
Cette réponse est basée sur les commentaires selon lesquels devicePixelRatio ne revient pas correctement sur la réponse de user1080381.
J'ai constaté que cette commande revenait de manière incorrecte dans certains cas également lorsque vous travaillez avec un ordinateur de bureau, Surface Pro 3 et Surface Pro 4.
Ce que j’ai trouvé, c’est que cela fonctionnait sur mon bureau, mais les SP3 et SP4 donnaient des numéros différents l’un de l’autre et le bureau.
J'ai remarqué cependant que le SP3 revenait à une fois et demie le niveau de zoom que j'attendais. Lorsque j’ai jeté un œil aux paramètres d’affichage, le SP3 était réglé à 150% au lieu des 100% que j’avais sur mon bureau.
La solution aux commentaires devrait donc être de diviser le niveau de zoom renvoyé par l’échelle de la machine sur laquelle vous vous trouvez.
J'ai pu obtenir l'échelle dans les paramètres Windows en procédant comme suit:
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor");
double deviceScale = Convert.ToDouble(searcher.Get().OfType<ManagementObject>().FirstOrDefault()["PixelsPerXLogicalInch"]);
int standardPixelPerInch = 96;
return deviceScale / standardPixelPerInch;
Donc, dans le cas de mon SP3, voici comment ce code apparaît à un zoom de 100%:
devicePixelRatio = 1.5
deviceScale = 144
deviceScale / standardPixelPerInch = 1.5
devicePixelRatio / (deviceScale / standardPixelPerInch) = 1
Multiplier par 100 dans la réponse originale de user1080381 vous donnerait alors un zoom de 100 (%).
J'ai cette solution pour mobile uniquement (testé avec Android):
jQuery(function($){
zoom_level = function(){
$("body").prepend('<div class="overlay" ' +
'style="position:fixed; top:0%; left:0%; ' +
'width:100%; height:100%; z-index:1;"></div>');
var ratio = $("body .overlay:eq(0)").outerWidth() / $(window).width();
$("body .overlay:eq(0)").remove();
return ratio;
}
alert(zoom_level());
});
Si vous voulez le niveau de zoom juste après le mouvement de pincement, vous devrez probablement définir un peu de délai en raison du délai de rendu (mais je ne suis pas sûr car je ne l'ai pas testé).
Si cela fonctionne actuellement, il doit encore être séparé par navigateur. Testé avec succès sur Chrome (75) et Safari (11.1) (aucune solution n'a encore été trouvée pour FF). La valeur du zoom est également correcte sur l'affichage de la rétine et les calculs sont déclenchés lors d'un événement de redimensionnement.
private pixelRatio() {
const styleString = "(min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 1.5),(-moz-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)";
const chromeRatio = (Math.round((this.window.outerWidth / this.window.innerWidth)*100) / 100);
const otherRatio = (Math.round(window.devicePixelRatio * 100) / 100);
const resizeValue = (this.isChrome()) ? chromeRatio : otherRatio;
return resizeValue || (this.window.matchMedia && this.window.matchMedia(styleString).matches ? 2 : 1) || 1;
}
private isChrome():boolean {
return (!!this.window.chrome && !(!!this.window.opera || this.window.navigator.userAgent.indexOf(' Opera') >= 0))
}
private chrome() {
const zoomChrome = Math.round(((this.window.outerWidth) / this.window.innerWidth)*100) / 100;
return {
zoom: zoomChrome,
devicePxPerCssPx: zoomChrome1 * this.pixelRatio()
};
}
Cela n’a pas été testé pour IE, mais si vous créez un élément elem
avec
min-width: 100%
puis
window.document.width / elem.clientWidth
vous donnera le niveau de zoom de votre navigateur (y compris le facteur document.body.style.zoom
).