javascript - Hur man upptäcker sidzoomnivå i alla moderna webbläsare?


  1. Hur kan jag upptäcka sidans zoomnivå i alla moderna webbläsare? Medan denna tråd berättar hur man gör det i IE7 och IE8, kan jag inte hitta en bra lösning som fungerar i alla webbläsare.

  2. Firefox sparar sidans zoomnivå för framtida åtkomst. Vid första sidladdningen, skulle jag kunna få zoomnivån? Någonstans läste jag att det fungerar när en zoomändring sker efter att sidan har laddats.

  3. Finns det ett sätt att fånga 'zoom'-händelsen?

Jag behöver detta eftersom några av mina beräkningar är pixelbaserade och de kan variera när man zoomar.

Modifierat exempel givet av @tfl

Denna sida visar olika höjdvärden när den zoomas. [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>

Svar #1

Nu är det ett ännu större kaos än vad det var när den här frågan först ställdes. Från att ha läst alla svar och blogginlägg jag kunde hitta, här är en sammanfattning. Jag har också satt upp den här sidan för att testa alla dessa metoder för att mäta zoomnivån. [↑ trasig länk. Arkiverad kopia → här].

Redigera (2011-12-12): Jag har lagt till ett projekt som kan klonas: https://github.com/tombigel/detect-zoom

  • IE8: screen.deviceXDPI/screen.logicalXDPI (eller, för zoomnivån i förhållande till standardzoom, screen.systemXDPI/screen.logicalXDPI)
  • IE7: var body=document.body,r=body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth; (tack vare detta exempel eller detta svar)
  • ENDAST FF3.5: screen.width/media query-skärmbredd (se nedan) (utnyttjar det faktum att screen.width använder enhetspixlar men MQ-bredd använder CSS-pixlar--tack vare Quirksmode-bredder)
  • FF3.6: ingen känd metod
  • FF4+: binärsökning för medieförfrågningar (se nedan)
  • WebKit: https://www.chromestatus.com/feature/5737866978131968 (tack till Teo i kommentarerna)
  • WebKit: mät den föredragna storleken på en div med -webkit-text-size-adjust:none.
  • WebKit: (trasig sedan r72591) document.width/jQuery(document).width() (tack till Dirk van Oosterbosch ovan). För att få förhållandet i termer av enhetspixlar (istället för relativt till standardzoom), multiplicera med window.devicePixelRatio.
  • Gammal WebKit? (iverifierat): parseInt(getComputedStyle(document.documentElement,null).width)/document.documentElement.clientWidth (från detta svar)
  • Opera: document.documentElement.offsetWidth/bredden på en position:fixed; width:100% div. Enligt Quirksmodes tabell över bredder sägs det vara en bugg; innerWidth bör vara CSS px. Vi använder elementet med position:fixed för att få viewportens bredd inklusive utrymmet där rullningslisternas finns; document.documentElement.clientWidth exkluderar denna bredd. Detta har varit trasigt sedan någon gång 2011; jag känner till inget sätt att få zoomnivån i Opera längre.
  • Annat: Flash-lösning från Sebastian
  • Opålitlig: lyssna på mus-händelser och mät förändring i screenX/förändring i clientX

Här är en binär sökning för Firefox 4, eftersom jag inte känner till någon variabel där den är tillgänglig:

var a = 0.1; // start of the search range
var b = 5; // end of the search range
var maxIter = 20; // maximum number of iterations
var epsilon = 0.01; // tolerance

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);

console.log(mozDevicePixelRatio)
console.log(ff35DevicePixelRatio)
<style id=binarysearch></style>
<div id=dummyElement>Dummy element to test media queries.</div>

Svar #2

Du kan försöka

var browserZoomLevel = Math.round(window.devicePixelRatio * 100);

Detta kommer att ge dig webbläsarens zoomprocentnivå på icke-retina-skärmar. För skärmar med hög DPI/retina skulle det ge olika värden (t.ex. 200 för Chrome och Safari, 140 för Firefox).

För att fånga Zoom-händelse kan du använda

$(window).resize(function() { 
// your code 
});

Svar #3

För mig, för Chrome/Webkit, fungerade inte document.width/jQuery(document).width(). När jag gjorde mitt fönster litet och zoomade in på min webbplats så att horisontella rullningslister dök upp, var document.width/jQuery(document).width() inte lika med 1 vid standardzoom. Detta beror på att document.width inkluderar delar av dokumentet utanför vyfönstret.

Att använda window.innerWidth och window.outerWidth fungerade. Av någon anledning mäts outerWidth i skärm pixlar i Chrome och innerWidth mäts i css-pixlar.

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";
}

Svar #4

Min kollega och jag använde skriptet från https://github.com/tombigel/detect-zoom. Dessutom skapade vi dynamiskt ett svg-element och kontrollerade dess currentScale-egenskap. Det fungerar utmärkt på Chrome och troligen på de flesta andra webbläsare också. På FF måste dock funktionen "zoom text endast" stängas av. SVG stöds på de flesta webbläsare. Vid tidpunkten för detta skrivande har det testats på IE10, FF19 och 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);

Svar #5

Du kan använda Visual Viewport API

Det är standard och fungerar både på dator och mobil: webbläsarstöd.

console.log(window.visualViewport.scale);

Svar #6

Jag fann denna artikel oerhört hjälpsam. Stort tack till yonran. Jag ville vidarebefordra några ytterligare lärdomar jag fann medan jag implementerade några av de tekniker han tillhandahöll. I FF6 och Chrome 9 lades stöd för media queries från JS till, vilket kan förenkla media query-metoden som är nödvändig för att bestämma zoom i FF. Se dokumentationen på MDN här. För mina ändamål behövde jag bara upptäcka om webbläsaren var in- eller utzoomad, jag hade inget behov av själva zoomnivån. Jag kunde få mitt svar med en rad JavaScript:

var isZoomed = window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;

Genom att kombinera detta med IE8+ och Webkit-lösningarna, som också var enkelrader, kunde jag upptäcka zoom på största delen av webbläsarna som besökte vår app med bara några få rader kod.

Svar #7

const zoom = ( window.outerWidth - 10 ) / window.innerWidth
console.log(zoom)

Det är allt du behöver.

Relaterade artiklar