在 JavaScript 中捕获浏览器的“缩放”事件

是否可以使用 JavaScript 检测用户何时更改页面中的缩放? 我只是想捕获一个“缩放”事件并对其作出响应(类似于 window.onresize 事件)。

谢谢。

201791 次浏览

没办法主动检测是否有变焦。我在这里找到了一个关于如何尝试实现它的好条目。

我找到了两种方法来检测 变焦级别。检测变焦的一种方法 水平的变化取决于 不放大百分比值 百分比值是相对于 视窗宽度,因此不受 如果你插入两个元素, 一个有百分比的位置, 一个位置相同 像素时,它们会分开 页面被缩放。查找 元素和元素的位置 你已经得到了变焦水平。看到测试 案件。 Http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3

你也可以使用上面的工具。问题在于,您或多或少地对页面是否已缩放进行了有根据的猜测。这在某些浏览器中会比其他浏览器工作得更好。

如果他们在缩放的时候加载了你的页面,那么就无法判断页面是否被缩放了。

我正在使用这段 JavaScript 来响应 Zoom 的“事件”。
它轮询窗口宽度。 (正如在这个页面(伊恩埃利奥特链接) : http://novemberborn.net/javascript/page-zoom-ff3 [存档]有所建议)

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

我想建议改进以前的解决方案,跟踪窗口宽度的变化。与保留您自己的事件侦听器数组不同,您可以使用现有的 javascript 事件系统,并在宽度变化时触发您自己的事件,并将事件处理程序绑定到它。

$(window).bind('myZoomEvent', function() { ... });


function pollZoomFireEvent()
{


if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}

节流/退出 可以帮助降低处理程序的调用率。

您还可以通过注入至少包含不可破坏空间(可能是隐藏空间)的 div 并定期检查其高度来获得文本大小调整事件和缩放因子。如果高度改变了,文本大小就改变了(你知道改变了多少——顺便说一句,如果窗口在整页模式下缩放,你仍然会得到正确的缩放因子,具有相同的高度/高度比)。

这对我有用:

        var deviceXDPI = screen.deviceXDPI;
setInterval(function(){
if(screen.deviceXDPI != deviceXDPI){
deviceXDPI = screen.deviceXDPI;
... there was a resize ...
}
}, 500);

它只需要在 IE8上。所有其他浏览器自然生成一个调整大小的事件。

有一个漂亮的插件构建的 yonran,可以做检测。这是他之前关于 StackOverflow 的 回答问题。它适用于大多数浏览器。申请简单如下:

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

演示

我正在回复一个3年前的链接,但我想这里有一个更可接受的答案,

创建.css 文件,

@media screen and (max-width: 1000px)
{
// things you want to trigger when the screen is zoomed
}

例子:-

@media screen and (max-width: 1000px)
{
.classname
{
font-size:10px;
}
}

当屏幕放大到大约125% 时,上面的代码使字体的大小为“10px”。您可以通过更改“1000px”的值来检查不同的缩放级别。

<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>

好消息 所有人一些人! 较新的浏览器会触发窗口大小调整事件时,缩放被改变。

在 iOS10上,可以向 touchmove事件添加一个事件侦听器,并检测页面是否与当前事件一起缩放。

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

虽然这是一个9年前的问题,问题仍然存在!

我一直在检测调整大小,而不包括缩放在一个项目中,所以我编辑了我的代码,使其工作,以检测调整大小和变焦相互排斥。它的工程 大部分的时间,所以如果 大部分是足够好的为您的项目,那么这应该是有帮助的!在我目前所测试的内容中,它检测到100% 的放大时间。唯一的问题是,如果用户得到疯狂(即。或者窗口滞后,它可以通过缩放而不是调整窗口大小来激发。

它通过检测 window.outerWidthwindow.outerHeight作为窗口大小的变化来工作,同时检测 window.innerWidthwindow.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);

注意: 我的解决方案类似于 KajMagnus 的,但这对我来说更有效。

让我们定义 px _ ratio 如下:

物理像素与 css 像素的比率。

如果任何一个缩放页面,视口 px (px 不同于像素)减少,应该适合屏幕,所以比例(物理像素/CSS _ px)必须变大。

但在窗口大小调整,屏幕尺寸减少以及像素。所以比率将保持。

放大: 触发 windows.resize 事件—— > 并更改 px _ ratio

但是

调整大小: 触发 windows.resize 事件—— > 不会改变 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

这里有一个干净的解决方案:

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

Something 调整大小事件通过将事件附加到 window上,然后读取 body或其他元素(例如 。 getBoundingClientRect ())的值来在现代浏览器上工作。

在一些早期的浏览器中,可以注册调整事件 任何 HTML 元素上的处理程序。仍然可以设置 onresize 属性或使用 addEventListener ()设置任何元素的处理程序。 但是,调整大小事件只触发窗口对象(即。 返回的处理程序)。 < strong > 只有在 窗口对象将接收调整事件 .

Something 调整您的选项卡或缩放,以触发下面的代码片段:

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


另一个现代的选择 : < a href = “ https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver”rel = “ nofollow noReferrer”> 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 任务过载。

根据 MDN,“ match Media”是完成这个 https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes的正确方法

这有点挑剔,因为每个实例一次只能看一个 MQ,所以如果你对 任何缩放级别的变化感兴趣,你需要做一堆匹配器。.但是由于浏览器负责发送事件,它可能仍然比轮询性能更好,你可以节流或去除回调,或将其固定到一个动画框架或其他东西上——这里有一个看起来很快捷的实现,如果你已经在依赖它,请随意切换到 _ 节流或其他任何东西。

运行代码片段并在浏览器中放大和缩小,注意标记中的更新值——我只在 Firefox 中测试过!如果你看到什么问题就告诉我。

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>

这里有一个本地化的方法(主要框架不能放大 Chrome,因为它们是 不支持被动事件行为)


//For Google Chrome
document.addEventListener("mousewheel", event => {
console.log(`wheel`);
if(event.ctrlKey == true)
{
event.preventDefault();
if(event.deltaY > 0) {
console.log('Down');
}else {
console.log('Up');
}
}
}, { passive: false });


// For Mozilla Firefox
document.addEventListener("DOMMouseScroll", event => {
console.log(`wheel`);
if(event.ctrlKey == true)
{
event.preventDefault();
if(event.detail > 0) {
console.log('Down');
}else {
console.log('Up');
}
}
}, { passive: false });