Событие изменения размера окна JavaScript
Как я могу подключиться к событию изменения размера окна браузера?
Существует способ прослушивания событий изменения размера в jQuery, но я бы предпочел не включать его в свой проект только по одному этому требованию.
12 ответов
JQuery это просто стандарт resize
Событие DOM, например.
window.onresize = function(event) {
...
};
jQuery может сделать некоторую работу, чтобы гарантировать, что событие resize будет срабатывать согласованно во всех браузерах, но я не уверен, что какой-либо из браузеров отличается, но я бы посоветовал вам протестировать в Firefox, Safari и IE.
Во-первых, я знаю addEventListener
Метод был упомянут в комментариях выше, но я не видел никакого кода. Поскольку это предпочтительный подход, вот он:
window.addEventListener('resize', function(event){
// do stuff here
});
Никогда не отменяйте функцию window.onresize.
Вместо этого создайте функцию для добавления прослушивателя событий к объекту или элементу. Это проверяет, что слушатели не работают, а затем переопределяет функцию объекта как последнее средство. Это предпочтительный метод, используемый в библиотеках, таких как jQuery.
object
: элемент или оконный объектtype
: изменить размер, прокрутить (тип события)callback
: ссылка на функцию
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;
}
};
Тогда используйте это так:
addEvent(window, "resize", function_reference);
или с анонимной функцией:
addEvent(window, "resize", function(event) {
console.log('resized');
});
Решение для 2018+:
Вы должны использовать ResizeObserver. Это будет нативное для браузера решение, которое имеет гораздо лучшую производительность, чем использование resize
событие. Кроме того, он не только поддерживает событие на document
но и на произвольном elements
,
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 поддерживает его, но другие браузеры, вероятно, последуют (скоро). На данный момент вы должны использовать полифилл.
Событие resize никогда не должно использоваться напрямую, так как оно запускается непрерывно при изменении размера.
Используйте функцию debounce, чтобы уменьшить лишние вызовы.
window.addEventListener('resize',debounce(handler, delay, immediate),false);
Вот распространенный дебат, распространяющийся по сети, хотя более продвинутые ищите, как featuerd в lodash.
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);
};
};
Это можно использовать как так...
window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);
Он никогда не будет срабатывать чаще, чем раз в 200 мс.
Для изменений мобильной ориентации используйте:
window.addEventListener('orientationchange', () => console.log('hello'), false);
Вот небольшая библиотека, которую я собрал, чтобы аккуратно позаботиться об этом.
Я верю, что @Alex V уже предоставил правильный ответ, но ответ требует некоторой модернизации, так как ему уже более пяти лет.
Есть два основных вопроса:
Никогда не используйте
object
в качестве имени параметра. Это зарезервированное слово. Учитывая сказанное, предоставляемая функция @Alex V не будет работать вstrict mode
,addEvent
Функция, предоставляемая @Alex V, не возвращаетevent object
еслиaddEventListener
метод используется. Другой параметр должен быть добавлен кaddEvent
функция, чтобы учесть это.
ПРИМЕЧАНИЕ. Новый параметр addEvent
был сделан необязательным, чтобы переход на эту новую версию функции не нарушал предыдущие вызовы этой функции. Все устаревшие варианты использования будут поддерживаться.
Вот обновленный addEvent
работать с этими изменениями:
/*
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;
};
Пример вызова к новому addEvent
функция:
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);
Спасибо за ссылку на мой пост в блоге на http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html.
Хотя вы можете просто подключиться к стандартному событию изменения размера окна, вы обнаружите, что в IE событие запускается один раз для каждого X и один раз для каждого движения оси Y, в результате чего запускается тонна событий, которые могут иметь производительность влияние на ваш сайт, если рендеринг является интенсивной задачей.
Мой метод предусматривает короткий тайм-аут, который отменяется при последующих событиях, чтобы событие не попадало в ваш код, пока пользователь не завершил изменение размера окна.
Следующее сообщение в блоге может быть полезно для вас: Исправление события изменения размера окна в IE
Он предоставляет этот код:
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); }
Уже упомянутые выше решения будут работать, если все, что вы хотите сделать, это изменить размер окна и только окна. Однако, если вы хотите, чтобы изменение размера распространялось на дочерние элементы, вам нужно будет распространить событие самостоятельно. Вот пример кода, чтобы сделать это:
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);
});
Обратите внимание, что дочерний элемент может вызывать
event.preventDefault();
на объекте события, который передается в качестве первого Arg события resize. Например:
var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
...
event.preventDefault();
});
Вы можете использовать следующий подход, который подходит для небольших проектов.
<body onresize="yourHandler(event)">
function yourHandler(e) {
console.log('Resized:', e.target.innerWidth)
}
<body onresize="yourHandler(event)">
Content... (resize browser to see)
</body>
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_];
}
}
}
<script language="javascript">
window.onresize = function() {
document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
}
</script>