JavaScript window resize event
如何挂钩浏览器窗口调整大小事件?
有一种侦听调整大小事件的jQuery方式,但我不希望仅出于这一要求就将其引入我的项目中。
jQuery只是包装了标准的
1 2 3 | window.onresize = function(event) { ... }; |
jQuery可以做一些工作来确保在所有浏览器中一致地触发resize事件,但是我不确定任何浏览器是否有所不同,但是我鼓励您在Firefox,Safari和IE中进行测试。
切勿覆盖window.onresize函数。
而是,创建一个将事件侦听器添加到对象或元素的函数。
这会检查并防止侦听器不起作用,然后作为最后手段重写该对象的功能。这是在jQuery之类的库中使用的首选方法。
1 2 3 4 5 6 7 8 9 10 | var addEvent = function(object, type, callback) { if (object == null || typeof(object) == 'undefined') return; if (object.addEventListener) { object.addEventListener(type, callback, false); } else if (object.attachEvent) { object.attachEvent("on" + type, callback); } else { object["on"+type] = callback; } }; |
然后使用是这样的:
1 | addEvent(window,"resize", function_reference); |
或具有匿名功能:
1 2 3 | addEvent(window,"resize", function(event) { console.log('resized'); }); |
首先,我知道上面的注释中已经提到了
1 2 3 | window.addEventListener('resize', function(event){ // do stuff here }); |
这是一个工作示例。
调整大小事件永远不要直接使用,因为它在调整大小时会连续触发。
使用去抖动功能来减轻过多的呼叫。
这是一种常见的在网上浮动的反跳,尽管确实会在lodash中寻找更高级的反跳。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | const debounce = (func, wait, immediate) => { var timeout; return () => { const context = this, args = arguments; const later = function() { timeout = null; if (!immediate) func.apply(context, args); }; const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; |
可以这样使用...
1 2 | window.addEventListener('resize', debounce(() => console.log('hello'), 200, false), false); |
每200ms发射一次就不会超过一次。
对于移动方向更改,请使用:
1 | window.addEventListener('orientationchange', () => console.log('hello'), false); |
我整理了一个小图书馆来妥善处理这个问题。
我确实相信@Alex V已经提供了正确的答案,但是答案确实需要一些现代化,因为它已经超过5年了。
有两个主要问题:
切勿使用
如果使用
注意:
这是具有以下更改的更新的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /* function: addEvent @param: obj (Object)(Required) - The object which you wish to attach your event to. @param: type (String)(Required) - The type of event you wish to establish. @param: callback (Function)(Required) - The method you wish to be called by your event listener. @param: eventReturn (Boolean)(Optional) - Whether you want the event object returned to your callback method. */ var addEvent = function(obj, type, callback, eventReturn) { if(obj == null || typeof obj === 'undefined') return; if(obj.addEventListener) obj.addEventListener(type, callback, eventReturn ? true : false); else if(obj.attachEvent) obj.attachEvent("on" + type, callback); else obj["on" + type] = callback; }; |
新的
1 2 3 4 5 6 7 8 9 10 11 12 13 | var watch = function(evt) { /* Older browser versions may return evt.srcElement Newer browser versions should return evt.currentTarget */ var dimensions = { height: (evt.srcElement || evt.currentTarget).innerHeight, width: (evt.srcElement || evt.currentTarget).innerWidth }; }; addEvent(window, 'resize', watch, true); |
2018年以上的解决方案:
您应该使用ResizeObserver。与使用
1
2
3
4
5
6
7
8
9
10
11 var ro = new ResizeObserver( entries => {
for (let entry of entries) {
const cr = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Element size: ${cr.width}px x ${cr.height}px`);
console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
}
});
// Observe one or multiple elements
ro.observe(someElement);
目前,只有Chrome支持它,但其他浏览器很可能会很快支持。现在,您必须使用polyfill。
感谢您在http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html中引用我的博客文章。
虽然您可以连接到标准窗口调整大小事件,但您会发现在IE中,该事件每X触发一次,每Y轴移动触发一次,从而导致触发大量事件,这些事件可能具有一定的性能如果渲染是一项繁重的任务,则会对您的网站产生影响。
我的方法涉及一个短暂的超时,该超时将在后续事件中取消,以便在用户完成调整窗口大小之前,该事件不会冒泡到您的代码中。
1 2 3 | window.onresize = function() { // your code }; |
以下博客文章可能对您有用:在IE中修复窗口调整大小事件
它提供了以下代码:
1
2
3
4
5
6
7
8
9
10 Sys.Application.add_load(function(sender, args) {
$addHandler(window, 'resize', window_resize);
});
var resizeTimeoutId;
function window_resize(e) {
window.clearTimeout(resizeTimeoutId);
resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}
如果您只想调整窗口和窗口的大小,则上面已经提到的解决方案将起作用。但是,如果您希望将调整大小传播到子元素,则需要自己传播事件。这是一些示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | window.addEventListener("resize", function () { var recResizeElement = function (root) { Array.prototype.forEach.call(root.childNodes, function (el) { var resizeEvent = document.createEvent("HTMLEvents"); resizeEvent.initEvent("resize", false, true); var propagate = el.dispatchEvent(resizeEvent); if (propagate) recResizeElement(el); }); }; recResizeElement(document.body); }); |
请注意,子元素可以调用
1 | event.preventDefault(); |
在作为调整大小事件的第一个Arg传入的事件对象上。例如:
1 2 3 4 5 | var child1 = document.getElementById("child1"); child1.addEventListener("resize", function (event) { ... event.preventDefault(); }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | var EM = new events_managment(); EM.addEvent(window, 'resize', function(win,doc, event_){ console.log('resized'); //EM.removeEvent(win,doc, event_); }); function events_managment(){ this.events = {}; this.addEvent = function(node, event_, func){ if(node.addEventListener){ if(event_ in this.events){ node.addEventListener(event_, function(){ func(node, event_); this.events[event_](win_doc, event_); }, true); }else{ node.addEventListener(event_, function(){ func(node, event_); }, true); } this.events[event_] = func; }else if(node.attachEvent){ var ie_event = 'on' + event_; if(ie_event in this.events){ node.attachEvent(ie_event, function(){ func(node, ie_event); this.events[ie_event](); }); }else{ node.attachEvent(ie_event, function(){ func(node, ie_event); }); } this.events[ie_event] = func; } } this.removeEvent = function(node, event_){ if(node.removeEventListener){ node.removeEventListener(event_, this.events[event_], true); this.events[event_] = null; delete this.events[event_]; }else if(node.detachEvent){ node.detachEvent(event_, this.events[event_]); this.events[event_] = null; delete this.events[event_]; } } } |
1 2 3 4 | <script language="javascript"> window.onresize = function() { document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%'; } |