是否可以使用 JavaScript 检测用户何时更改页面的缩放比例?我只是想捕捉一个“缩放”事件并响应它(类似于 window.onresize 事件)。
谢谢。
是否可以使用 JavaScript 检测用户何时更改页面的缩放比例?我只是想捕捉一个“缩放”事件并响应它(类似于 window.onresize 事件)。
谢谢。
没有办法主动检测是否有缩放。我在这里找到了一个关于如何尝试实现它的好条目。
我发现了两种检测缩放级别的方法。检测缩放级别变化的一种方法依赖于百分比值未缩放的事实。百分比值是相对于视口宽度的,因此不受页面缩放的影响。如果您插入两个元素,一个具有百分比位置,另一个具有相同位置(以像素为单位),当页面缩放时,它们将分开。找到两个元素的位置之间的比率,你就得到了缩放级别。见测试用例。 http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
您也可以使用上述帖子的工具来完成。问题是您或多或少地对页面是否缩放进行了有根据的猜测。这在某些浏览器中会比其他浏览器更好。
如果他们在缩放时加载您的页面,则无法判断页面是否已缩放。
让我们定义 px_ratio 如下:
px 比率 = 物理像素与 css px 的比率。
如果任何一个缩放页面,视口 pxes(px 与 pixel 不同)会减小并且应该适合屏幕,因此比例(物理像素/ CSS_px)必须变大。
但在窗口大小调整中,屏幕尺寸和像素一样减小。所以这个比例会保持。
但
调整大小:触发 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和Physical Pixel的区别。
https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e
好消息每个人有些人!较新的浏览器将在缩放更改时触发窗口调整大小事件。
我正在使用这段 JavaScript 来响应 Zoom“事件”。
它轮询窗口宽度。(正如这个页面上的一些建议(Ian Elliott 链接到): http: //novemberborn.net/javascript/page-zoom-ff3 [archive])
使用 Chrome、Firefox 3.6 和 Opera 测试,而不是 IE。
问候,马格努斯
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上回答的问题。它适用于大多数浏览器。申请就这么简单:
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
: "");
}
虽然这是一个 9 岁的问题,但问题仍然存在!
我在项目中排除缩放时一直在检测调整大小,因此我编辑了我的代码以使其能够检测调整大小和缩放相互排斥。它在大多数情况下都有效,所以如果大多数都对您的项目足够好,那么这应该会有所帮助!到目前为止,它在我测试的内容中检测到 100% 的缩放时间。唯一的问题是,如果用户变得疯狂(即痉挛地调整窗口大小)或窗口滞后,它可能会作为缩放而不是窗口调整大小触发。
它的工作原理是检测窗口大小的变化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);
注意:我的解决方案类似于 KajMagnus 的解决方案,但这对我来说效果更好。
⬤ resize 事件在现代浏览器上通过将事件附加到 上window
,然后读取body
或其他元素的值,例如(.getBoundingClientRect())。
在一些早期的浏览器中,可以在任何 HTML 元素上注册调整大小事件处理程序。仍然可以设置 onresize 属性或使用 addEventListener() 在任何元素上设置处理程序。然而,调整大小事件仅在窗口对象上触发(即由 document.defaultView 返回)。只有在窗口对象上注册的处理程序才会接收调整大小事件。
⚠️ 调整标签大小或缩放以触发此代码段:
window.addEventListener("resize", getSizes, false)
function getSizes(){
let body = document.body
console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}
⬤ 另一种选择:ResizeObserver API
根据您的布局,您可以注意调整特定元素的大小。
这适用于“响应式”布局,因为容器框在缩放时会调整大小。
function watchBoxchange(e){
// console.log(e[0].contentBoxSize.inlineSize+" "+e[0].contentBoxSize.blockSize)
info.textContent = e[0].contentBoxSize.inlineSize+" * "+e[0].contentBoxSize.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 。
我想建议通过跟踪窗口宽度的变化来改进以前的解决方案。您可以使用现有的 javascript 事件系统并在宽度更改时触发您自己的事件,并将事件处理程序绑定到它,而不是保留自己的事件侦听器数组。
$(window).bind('myZoomEvent', function() { ... });
function pollZoomFireEvent()
{
if ( ... width changed ... ) {
$(window).trigger('myZoomEvent');
}
}
Throttle/debounce可以帮助降低处理程序的调用率。
这是一个干净的解决方案:
// 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);
});
根据 MDN,“matchMedia”是执行此操作的正确方法https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
这有点挑剔,因为每个实例一次只能观看一个 MQ,所以如果您对任何缩放级别更改感兴趣,您需要制作一堆匹配器。但由于浏览器负责发出事件,它可能仍然比轮询性能更高,您可以限制或消除回调或将其固定到动画帧或其他东西 - 这是一个看起来非常敏捷的实现,如果您已经依赖它,请随意交换 _throttle 或其他任何东西。
运行代码片段并在浏览器中放大和缩小,注意标记中的更新值 - 我只在 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>
您还可以通过注入至少包含不可破坏空间(可能是隐藏的)的 div 并定期检查其高度来获取文本调整大小事件和缩放因子。如果高度发生变化,则文本大小发生了变化,(并且您知道多少 - 顺便说一句,如果窗口在全页模式下放大,您仍然会得到正确的缩放因子,高度相同 /高比)。
<script>
var zoomv = function() {
if(topRightqs.style.width=='200px){
alert ("zoom");
}
};
zoomv();
</script>
在 iOS 10 上,可以为事件添加事件侦听器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;
});
这是一种原生方式(主要框架无法放大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 });
我正在回复一个 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”的值来检查不同的缩放级别。