JavaScript のウィンドウリサイズイベント
ブラウザウィンドウのリサイズイベントにどのようにフックできますか?
リサイズイベントを監視するための jQuery の方法はありますが、この1つの要件のためだけにプロジェクトに導入したくはありません。
回答 #1
ベストプラクティスは、リサイズイベントを置き換えるのではなく、追加することです:
window.addEventListener('resize', function(event) {
...
}, true);
別の方法として、DOMイベントの単一のハンドラーを作成することがあります(ただし一つしか持てません)、例えば。
window.onresize = function(event) {
...
};
jQueryは、リサイズイベントがすべてのブラウザで一貫して発火するようにいくらか作業を行うかもしれませんが、どのブラウザが異なるかはよく分かりません。しかし、Firefox、Safari、IEでテストすることをお勧めします。
回答 #2
まず最初に、上のコメントでaddEventListenerメソッドが言及されていることは知っていますが、コードは見当たりませんでした。推奨される方法なので、こちらがそのコードです:
window.addEventListener('resize', function(event){
// do stuff here
});
こちらが動作するサンプルです。
回答 #3
window.onresize 関数を上書きしてはいけません。
代わりに、オブジェクトや要素にイベントリスナーを追加する関数を作成します。これはリスナーが動作しない場合を確認し、最後の手段としてオブジェクトの関数を上書きします。これは、jQueryのようなライブラリで使用される推奨される方法です。
object: 要素またはウィンドウオブジェクト
type: resize、scroll(イベントタイプ)
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');
});
回答 #4
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);
現在、Firefox、Chrome、Safari、Edge がそれをサポートしています。他の(および古い)ブラウザでは、ポリフィルを使用する必要があります。
回答 #5
リサイズイベントは、リサイズ中に継続的に発火するため、直接使用すべきではありません。
過剰な呼び出しを緩和するためにデバウンス関数を使用してください。
window.addEventListener('resize',debounce(handler, delay, immediate),false);これはネット上でよく見かけるデバウンスですが、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);
これをきちんと処理するために私がまとめた小さなライブラリです。
回答 #6
私は正しい答えはすでに@Alex Vによって提供されていると信じていますが、その答えは今や5年以上経っているため、いくらかの更新が必要です。
主な問題は二つあります。
パラメーター名として
objectを使用しないでください。それは予約語です。これを踏まえると、@Alex V が提供した関数はstrict modeでは動作しません。@Alex V が提供する
addEvent関数は、addEventListenerメソッドが使用された場合にevent objectを返しません。このため、これを可能にするために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);
