如何在所有现代浏览器中检测页面缩放级别?

  1. 如何在所有现代浏览器中检测页面缩放级别? 虽然这个线程告诉我如何在IE7和IE8中做到这一点,但我找不到一个好的跨浏览器解决scheme。

  2. Firefox存储页面缩放级别以供将来访问。 在第一页加载,我可以得到缩放级别? 我读过的某个地方加载页面之后发生缩放变化时会起作用。

  3. 有没有办法来捕捉'zoom'事件?

我需要这个,因为我的一些计算是基于像素的,并且在放大时可能会波动。


由@tfl给出的修改样本

缩放时,此页面会提示不同的高度值。 [的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> 

现在比第一次问这个问题还要大。 从阅读所有的答复和博客文章,我可以find,这里是一个总结。 我也设置了这个页面来testing所有这些测量缩放级别的方法 。

编辑 (2011-12-12):我已经添加了一个可以克隆的项目: https : //github.com/tombigel/detect-zoom

  • IE8screen.deviceXDPI / screen.logicalXDPI (或者,对于相对于默认缩放的缩放级别, screen.systemXDPI / screen.logicalXDPI
  • IE7var body = document.body,r = body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth; var body = document.body,r = body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth; (感谢这个例子或这个答案 )
  • FF3.5 ONLYscreen.width / media查询屏幕宽度(参见下面)(利用screen.width使用设备像素,但MQ宽度使用CSS像素 – 归功于Quirksmode宽度 )
  • FF3.6 :没有已知的方法
  • FF4 + :媒体查询二进制search(见下文)
  • WebKit :用-webkit-text-size-adjust:none测量div的首选大小。
  • WebKit :(从r72591开始 ) document.width / jQuery(document).width() (感谢上面的Dirk van Oosterbosch )。 要根据设备像素(而不是相对于默认缩放)获取比率,请乘以window.devicePixelRatio
  • 旧的WebKit?parseInt(getComputedStyle(document.documentElement,null).width) / document.documentElement.clientWidth ): parseInt(getComputedStyle(document.documentElement,null).width) / document.documentElement.clientWidth (from this answer )
  • Operadocument.documentElement.offsetWidth / position:fixed; width:100%宽度position:fixed; width:100% position:fixed; width:100% div。 从这里 ( Quirksmode的宽度表表示这是一个错误; innerWidth应该是CSS px)。 我们使用position:fixed元素来获取视口的宽度, 包括滚动条所在的空间 ; document.documentElement.clientWidth不包括这个宽度。 自2011年的某个时候以来,这已经被打破。 我不知道如何在Opera中获得缩放级别。
  • 其他 : 塞巴斯蒂安的Flash解决scheme
  • 不可靠:收听鼠标事件并测量clientX中screenX / change的变化

下面是Firefox 4的二进制search,因为我不知道它暴露的任何variables:

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

感谢伟大的总结。

对于我来说,对于Chrome / Webkit, document.width / jQuery(document).width()不起作用。 当我缩小窗口,放大到我的网站,使水平滚动条出现时, document.width / jQuery(document).width()在默认缩放时不等于1。 这是因为document.width包含视口之外的部分文档。

使用window.innerWidthwindow.outerWidth工作。 出于某种原因在Chrome中,outerWidth以屏幕像素为单位进行测量,innerWidth以css像素单位进行测量。

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

你可以试试

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

这会给你浏览器的缩放比例级别。

捕捉缩放事件,你可以使用

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

我的同事和我从https://github.com/tombigel/detect-zoom使用脚本。; 另外,我们还dynamic地创build了一个svg元素并检查它的currentScale属性。 它在Chrome浏览器以及大多数浏览器上运行良好。 在FF上,“仅缩放文本”function必须closures。 大多数浏览器都支持 SVG。 在写这篇文章的时候,在IE10,FF19和Chrome28上进行了testing。

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

我发现这篇文章非常有帮助。 非常感谢yonran。 我想传递一些额外的学习,同时实施他提供的一些技巧。 在FF6和Chrome 9中,增加了对来自JS的媒体查询的支持,这可以大大简化确定FF放大所需的媒体查询方法。 在这里查看MDN的文档。 出于我的目的,我只需要检测浏览器是放大还是缩小,我不需要实际的缩放因子。 我能够用一行JavaScript获得我的答案:

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

结合IE8 +和Webkit解决scheme(这也是单行的),我能够在只有几行代码的情况下在绝大多数浏览器上检测到缩放。

 zoom = ( window.outerWidth - 10 ) / window.innerWidth 

这就是你所需要的。

这对我在基于webkit的浏览器(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; } 

虽然似乎在Firefox中工作。

这也适用于WebKit:

 var zoomLevel = document.width / document.body.clientWidth; 

在Internet Explorer 7,8和9中,这是有效的:

 function getZoom() { var screen; screen = document.frames.screen; return ((screen.deviceXDPI / screen.systemXDPI) * 100 + 0.9).toFixed(); } 

添加“+0.9”是为了防止舍入误差(否则,当浏览器缩放分别设置为105%和110%时,将得到104%和109%)。

在IE6中变焦不存在,所以不需要检查变焦。

您的计算仍然基于一些CSS像素。 他们现在在屏幕上只是一个不同的大小。 这是整页缩放的一点。

你想在一个192dpi设备上的浏览器上发生什么,因此一个图像中的每个像素通常显示四个设备像素? 在50%变焦的情况下,该设备现在在一个设备像素中显示一个图像像素。

我想到的是:

1) position:fixed <div>width:100%id = zoomdiv

2)当页面加载时:

 zoomlevel=$("#zoomdiv").width()*1.0 / screen.availWidth 

它为我工作ctrl+ctrl-放大。

或者我可以将该行添加到$(window).onresize()事件以获取活动缩放级别


码:

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

PS:这是我的第一篇文章,赦免任何错误

截至2016年1月,我有一个解决scheme。testing在Chrome,Firefox和MS Edge浏览器上工作。

原则如下。 收集2个相距甚远的MouseEvent点。 每个鼠标事件都带有屏幕和文档坐标。 测量两个坐标系中2点之间的距离。 虽然由于浏览器家具的缘故,坐标系之间存在可变的固定偏移量,但如果页面没有放大,点之间的距离应该是相同的。 指定“相距甚远”(我把它作为12个像素)的原因是可以检测到较小的缩放变化(例如90%或110%)。

参考: https : //developer.mozilla.org/en/docs/Web/Events/mousemove

脚步:

  1. 添加一个鼠标移动侦听器

     window.addEventListener("mousemove", function(event) { // handle event }); 
  2. 从鼠标事件捕获4个测量结果:

     event.clientX, event.clientY, event.screenX, event.screenY 
  3. 测量客户端系统中2点之间的距离d_c

  4. 测量屏幕系统中2点之间的距离d_s

  5. 如果d_c!= d_s,则应用缩放。 两者之间的差异告诉你的变焦量。

NB只有很less的距离计算,例如,当你可以采样一个远离前一个的新鼠标事件。

限制:假设用户至less会移动鼠标,直到这个时候缩放是不可知的。

没有testing这个IE浏览器,但如果你做一个元素elem

 min-width: 100% 

然后

 window.document.width / elem.clientWidth 

会给你你的浏览器缩放级别(包括document.body.style.zoom因子)。

这是为Chrome ,在user800583回答 …

我花了几个小时解决这个问题,并没有find更好的方法,但是:

  • 有16'zoomLevel'而不是10
  • 当Chrome是全屏/最大化的比例是window.outerWidth/window.innerWidth ,当它不是,这个比例似乎是(window.outerWidth-16)/window.innerWidth ,但是第一种情况可以接近第二一。

所以我来到以下…

但是这种方法有一定的局限性:例如,如果用应用程序窗口来播放手风琴(快速放大和缩小窗口的宽度),那么尽pipe缩放级别没有变化(可能是outerWidth和innerWidth不是在同一时间完全更新)。

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

如果你想要的因素:

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

只有移动设备的这个解决scheme(与Androidtesting):

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

如果你想要在缩放之后立即放大缩放级别,你可能需要设置一些延迟,因为渲染延迟(但是我不确定,因为我没有testing)。

 function supportFullCss3() { var div = document.createElement("div"); div.style.display = 'flex'; var s1 = div.style.display == 'flex'; var s2 = 'perspective' in div.style; return (s1 && s2); }; function getZoomLevel() { var screenPixelRatio = 0, zoomLevel = 0; if(window.devicePixelRatio && supportFullCss3()) screenPixelRatio = window.devicePixelRatio; else if(window.screenX == '0') screenPixelRatio = (window.outerWidth - 8) / window.innerWidth; else { var scr = window.frames.screen; screenPixelRatio = scr.deviceXDPI / scr.systemXDPI; } //--------------------------------------- if (screenPixelRatio <= .11){ //screenPixelRatio >= .01 && zoomLevel = "-7"; } else if (screenPixelRatio <= .25) { zoomLevel = "-6"; }else if (screenPixelRatio <= .33) { zoomLevel = "-5.5"; } else if (screenPixelRatio <= .40) { zoomLevel = "-5"; } else if (screenPixelRatio <= .50) { zoomLevel = "-4"; } else if (screenPixelRatio <= .67) { zoomLevel = "-3"; } else if (screenPixelRatio <= .75) { zoomLevel = "-2"; } else if (screenPixelRatio <= .85) { zoomLevel = "-1.5"; } else if (screenPixelRatio <= .98) { zoomLevel = "-1"; } else if (screenPixelRatio <= 1.03) { zoomLevel = "0"; } else if (screenPixelRatio <= 1.12) { zoomLevel = "1"; } else if (screenPixelRatio <= 1.2) { zoomLevel = "1.5"; } else if (screenPixelRatio <= 1.3) { zoomLevel = "2"; } else if (screenPixelRatio <= 1.4) { zoomLevel = "2.5"; } else if (screenPixelRatio <= 1.5) { zoomLevel = "3"; } else if (screenPixelRatio <= 1.6) { zoomLevel = "3.3"; } else if (screenPixelRatio <= 1.7) { zoomLevel = "3.7"; } else if (screenPixelRatio <= 1.8) { zoomLevel = "4"; } else if (screenPixelRatio <= 1.9) { zoomLevel = "4.5"; } else if (screenPixelRatio <= 2) { zoomLevel = "5"; } else if (screenPixelRatio <= 2.1) { zoomLevel = "5.2"; } else if (screenPixelRatio <= 2.2) { zoomLevel = "5.4"; } else if (screenPixelRatio <= 2.3) { zoomLevel = "5.6"; } else if (screenPixelRatio <= 2.4) { zoomLevel = "5.8"; } else if (screenPixelRatio <= 2.5) { zoomLevel = "6"; } else if (screenPixelRatio <= 2.6) { zoomLevel = "6.2"; } else if (screenPixelRatio <= 2.7) { zoomLevel = "6.4"; } else if (screenPixelRatio <= 2.8) { zoomLevel = "6.6"; } else if (screenPixelRatio <= 2.9) { zoomLevel = "6.8"; } else if (screenPixelRatio <= 3) { zoomLevel = "7"; } else if (screenPixelRatio <= 3.1) { zoomLevel = "7.1"; } else if (screenPixelRatio <= 3.2) { zoomLevel = "7.2"; } else if (screenPixelRatio <= 3.3) { zoomLevel = "7.3"; } else if (screenPixelRatio <= 3.4) { zoomLevel = "7.4"; } else if (screenPixelRatio <= 3.5) { zoomLevel = "7.5"; } else if (screenPixelRatio <= 3.6) { zoomLevel = "7.6"; } else if (screenPixelRatio <= 3.7) { zoomLevel = "7.7"; } else if (screenPixelRatio <= 3.8) { zoomLevel = "7.8"; } else if (screenPixelRatio <= 3.9) { zoomLevel = "7.9"; } else if (screenPixelRatio <= 4) { zoomLevel = "8"; } else if (screenPixelRatio <= 4.1) { zoomLevel = "8.1"; } else if (screenPixelRatio <= 4.2) { zoomLevel = "8.2"; } else if (screenPixelRatio <= 4.3) { zoomLevel = "8.3"; } else if (screenPixelRatio <= 4.4) { zoomLevel = "8.4"; } else if (screenPixelRatio <= 4.5) { zoomLevel = "8.5"; } else if (screenPixelRatio <= 4.6) { zoomLevel = "8.6"; } else if (screenPixelRatio <= 4.7) { zoomLevel = "8.7"; } else if (screenPixelRatio <= 4.8) { zoomLevel = "8.8"; } else if (screenPixelRatio <= 4.9) { zoomLevel = "8.9"; } else if (screenPixelRatio <= 5) { zoomLevel = "9"; }else { zoomLevel = "unknown"; } return zoomLevel; }; 

这个答案是基于关于devicePixelRatio在user1080381的答案上​​不正确地回来的评论。

我发现在使用桌面,Surface Pro 3和Surface Pro 4时,在某些情况下,此命令也会错误地回来。

我发现,它在我的桌面上工作,但SP3和SP4给对方和桌面不同的数字。

我注意到,虽然SP3回到了我预期的缩放级别的1.5倍。 当我看看显示设置,SP3实际上设置为150%,而不是我在桌面上的100%。

所以,评论的解决scheme应该是将返回的缩放级别除以您当前所在机器的比例。

通过执行以下操作,我可以在Windows设置中获取比例:

 ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor"); double deviceScale = Convert.ToDouble(searcher.Get().OfType<ManagementObject>().FirstOrDefault()["PixelsPerXLogicalInch"]); int standardPixelPerInch = 96; return deviceScale / standardPixelPerInch; 

所以在我的SP3的情况下,这是代码看起来如何100%缩放:

 devicePixelRatio = 1.5 deviceScale = 144 deviceScale / standardPixelPerInch = 1.5 devicePixelRatio / (deviceScale / standardPixelPerInch) = 1 

乘以user1080381的原始答案中的100,然后会给你一个100(%)的缩放。

这里不变!

 <html> <head> <title></title> </head> <body> <div id="xy" style="width:400px;"> foobar </div> <div> <button onclick="alert(document.getElementById('xy').style.width);">Show</button> </div> </body> </html> 

创build一个简单的html文件,点击button。 不pipe什么缩放级别:它会显示你的宽度400px(至less用firefox和IE8)

这可能或可能不会帮助任何人,但我有一个页面,我不能正确居中,无论我尝试了什么CSS技巧,所以我写了一个JQuery文件呼叫中心页面:

浏览器的缩放级别出现问题,如果您是100%,125%,150%等,页面会发生变化

下面的代码位于名为centerpage.js的JQuery文件中。

从我的页面,我不得不链接到JQuery和这个文件,以使其工作,即使我的母版页已经有一个链接到JQuery。

 <title>Home Page.</title> <script src="Scripts/jquery-1.7.1.min.js"></script> <script src="Scripts/centerpage.js"></script> 

centerpage.js

 // centering page element function centerPage() { // get body element var body = document.body; // if the body element exists if (body != null) { // get the clientWidth var clientWidth = body.clientWidth; // request data for centering var windowWidth = document.documentElement.clientWidth; var left = (windowWidth - bodyWidth) / 2; // this is a hack, but it works for me a better method is to determine the // scale but for now it works for my needs if (left > 84) { // the zoom level is most likely around 150 or higher $('#MainBody').removeClass('body').addClass('body150'); } else if (left < 100) { // the zoom level is most likely around 110 - 140 $('#MainBody').removeClass('body').addClass('body125'); } } } // CONTROLLING EVENTS IN jQuery $(document).ready(function() { // center the page centerPage(); }); 

另外,如果你想中心面板:

 // centering panel function centerPanel($panelControl) { // if the panel control exists if ($panelControl && $panelControl.length) { // request data for centering var windowWidth = document.documentElement.clientWidth; var windowHeight = document.documentElement.clientHeight; var panelHeight = $panelControl.height(); var panelWidth = $panelControl.width(); // centering $panelControl.css({ 'position': 'absolute', 'top': (windowHeight - panelHeight) / 2, 'left': (windowWidth - panelWidth) / 2 }); // only need force for IE6 $('#backgroundPanel').css('height', windowHeight); } } 

FireFox 16+的一个解决方法是纯粹使用JavaScript来查找DPPX(缩放级别):

 var dppx = (function (precision) { var searchDPPX = function(level, min, divisor) { var wmq = window.matchMedia; while (level >= min && !wmq("(min-resolution: " + (level/divisor) + "dppx)").matches) { level--; } return level; }; var maxDPPX = 5.0; // Firefox 22 has 3.0 as maximum, but testing a bit greater values does not cost much var minDPPX = 0.1; // Firefox 22 has 0.3 as minimum, but testing a bit smaller values does not cost anything var divisor = 1; var result; for (var i = 0; i < precision; i++) { result = 10 * searchDPPX (maxDPPX, minDPPX, divisor); maxDPPX = result + 9; minDPPX = result; divisor *= 10; } return result / divisor; }) (5); 

这很好:

 zoom = ( window.outerWidth - (window.outerWidth*0.1) ) / window.innerWidth; 

基本上,我们有:

  • window.devicePixelRatio考虑到浏览器级别的缩放*以及系统缩放/像素密度。
    * – 在Mac / Safari的缩放级别没有考虑在内
  • 媒体查询
  • vw / vh CSS单位
  • 在缩放级别改变时触发的resize事件导致窗口改变的有效大小

这对正常的用户体验应该是足够的。 如果您需要检测缩放级别,这可能是UIdevise不好的标志。

音高缩放比较难以追踪,目前尚未考虑。

这是问题被张贴像年龄回来,但今天当我正在寻找相同的答案“如何检测放大和缩小事件”,我找不到一个适合所有浏览器的答案。

就像现在一样:对于Firefox / Chrome / IE8和IE9,放大和缩小会触发一个window.resize事件。 这可以使用以下方法捕获:

 $(window).resize(function() { //YOUR CODE. });