是否可以使用JavaScript检测用户在页面中更改缩放比例?我想捕获“缩放”事件并对其做出响应(类似于window.onresize事件)。
谢谢。
是否可以使用JavaScript检测用户在页面中更改缩放比例?我想捕获“缩放”事件并对其做出响应(类似于window.onresize事件)。
谢谢。
无法主动检测是否有缩放。我在这里找到了一个很好的入门指南,讲述了如何尝试实现它。
我发现了两种检测缩放级别的方法。一种检测缩放级别变化的方法是基于百分比值不受缩放影响的事实。百分比值相对于视口宽度,因此不受页面缩放的影响。如果插入两个元素,一个使用百分比位置,另一个使用相同的像素位置,则它们将在页面缩放时移开。找到两个元素位置之间的比率,即可得到缩放级别。请参见测试用例。 http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
你也可以使用上面文章中提到的工具来实现缩放检测。但问题是你更多地是在猜测页面是否已经缩放。这在某些浏览器中效果会比其他浏览器好。
如果他们在缩放状态下加载你的页面,就无法判断页面是否被缩放。
document.body.offsetWidth
。 - Samie Bencherif让我们来定义px_ratio:
px_ratio = 物理像素和CSS像素的比例。
如果有人缩放页面,视口像素(px)会减少并应适应屏幕,因此比例(物理像素/CSS像素)必须变大。
但在窗口调整大小时,屏幕尺寸以及像素(px)也会减少,因此比例将保持不变。
但是
调整大小:触发窗口调整大小事件-->不会改变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;
}
}
关键点在于CSS PX和物理像素之间的区别。
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
好消息,一些人!当缩放比例更改时,更新的浏览器将触发窗口调整大小事件。
我正在使用这段 JavaScript 来响应 Zoom "事件"。
它轮询窗口宽度。
(正如 Ian Elliott 在这个页面上所建议的那样:http://novemberborn.net/javascript/page-zoom-ff3[archive])
在 Chrome、Firefox 3.6 和 Opera 中测试过,但不适用于 IE。
敬礼,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);
})();
var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);
只有在IE8上需要这个事件。其他浏览器自然会生成一个调整大小的事件。
有一个很棒的插件是由yonran
开发的,可以进行检测。以下是他之前在StackOverflow上回答的问题链接:answered。它适用于大多数浏览器。应用非常简单:
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
: "");
}
window.outerWidth
或window.outerHeight
的改变作为窗口调整大小,同时检测window.innerWidth
或window.innerHeight
的独立变化作为缩放。
//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);
0.05
这样的魔数而不提供一个好的解释。 ;-)例如,我知道在 Chrome 中,特别是 10% 是浏览器将缩放的最小量,在其他浏览器中是否也是如此并不清楚。顺便说一下,始终确保您的代码经过测试,并准备好为其辩护或改进。 - Nolo⬤ 调整窗口大小事件 通过在 window
上附加事件,然后读取body
或其他元素(例如(.getBoundingClientRect()))的值,在现代浏览器上工作。
在一些早期的浏览器中,可以在任何 HTML 元素上注册 resize 事件处理程序。仍然可以设置 onresize 属性或使用 addEventListener() 在任何元素上设置处理程序。但是,调整大小事件只在 window 对象上 (即由 document.defaultView 返回) 触发。只有在 window 对象上注册的处理程序才会接收到调整大小事件。
⚠️ 调整标签页或缩放以触发此片段:
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
body.width = window.innerWidth
body.height = window.innerHeight
console.log(body.width +"px x "+ body.height + "px")
}
getSizes()
⬤ 另一种现代的替代方案: ResizeObserver API
根据你的布局,你可以监视特定元素的大小调整。
这在“响应式”布局中非常有效,因为当缩放时,容器框会被重新调整大小。
function watchBoxchange(e){
info.textContent = e[0].contentBoxSize[0].inlineSize+" x "+e[0].contentBoxSize[0].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>
请注意不要从用户手势事件中过度加载JavaScript任务。只有在需要重新绘制时才使用requestAnimationFrame。
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>
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Throttle/debounce可以帮助减少处理程序的调用速率。