PC端实现方法:
resize事件进行判断页面是否缩放会伴随一些不必要的消耗,因为当用户改变窗体的尺寸,或者设备发生旋转,或者设备打开了开发者工具等,都会触发resize事件,但是,显然,这些触发resize事件的场景和页面缩放是没有关系的,而且这些场景才是真正的常态发生的,缩放才是小众发生的。
那有没有其他什么办法更高效地检测浏览器是否发生的页面缩放呢?
此时可以试试matchMedia()
方法,语法如下:
let mql = window.matchMedia(mediaString);
mql这个对象包含若干属性和方法,例如:
mql.matches
布尔值,表示当前是否匹配指定的媒体查询。
mql.media
字符串,返回编译后的媒体查询字符串。
mql.onchange
媒体查询改变时候的回调。
mql.addListener(fn)
fn参数是事件函数,媒体查询匹配状态变化时候执行。(此API已经不推荐使用)
mql.removeListener(fn)
fn参数是事件函数,移除绑定的事件。(此API已经不推荐使用)
使用示例:
let originPixelRatio = localStorage.devicePixelRatio; if (!originPixelRatio) { originPixelRatio = window.devicePixelRatio; if (Number.isInteger(originPixelRatio)) { localStorage.devicePixelRatio = originPixelRatio; } } // 设备相似比变化时候的处理函数 let mqListener = function () { let currentPixelRatio = window.devicePixelRatio; console.log('缩放比例是:' + currentPixelRatio / originPixelRatio); // 移除之前的查询检测 this.removeEventListener('change', mqListener); // 使用新的查询检测 matchMedia(`(resolution: ${currentPixelRatio}dppx)`).addEventListener('change', mqListener); }; // 添加媒体查询匹配变化事件 matchMedia(`(resolution: ${originPixelRatio}dppx)`).addEventListener('change', mqListener);
为何要不断移除事件?
matchMedia()
绑定的change事件,只会在查询状态改变时候触发,例如,原始的设备像素比(单位就是dppx)是1,则浏览器第一次放大和缩小的时候,change事件会执行,因为状态从匹配变成了不匹配,但是,如果继续放大和缩小,则change事件不再触发,因为状态一直是不匹配。
因此,逻辑实现的时候,需要试试更新媒体查询语句,绑定新的change事件,这样,任意的设备像素比变化都可以被检测到。
移动端实现方法
visualViewport与手势缩放识别:
实际上,页面的缩放比例,浏览器是提供了原生的API的,那就是window.visualViewport.scale
。
visualViewport
对象包括很多属性,例如宽高、偏移大小等,其中,我认为最稀缺的属性就是scale,可以返回当前页面因为双指缩放带来的缩放比例。
移动设备专享
visualViewport.scale
看起来给浏览器缩放识别带来了曙光,确实如此,但是,如果大家在PC端进行测试,会发现visualViewport.scale
永远发挥的是1
,无论页面通过 Ctrl+/Ctrl-组合键如何的缩小放大,都是1
。
这是bug吗?
不是的,因为返回的虚拟视区的pinch-zoom缩放比例,表示手势缩放。
因此,visualViewport.scale
只能在移动端使用
相应的js:(当用户缩放页面的时候会触发窗体的resize事件)
<div id = result></div>
window.visualViewport.addEventListener('resize', function () { result.innerHTML = '手势缩放比例:' + this.scale; });