Ich habe das folgende Beispiel-HTML, es gibt ein DIV, das 100% Breite hat. Es enthält einige Elemente. Während der Größenänderung von Fenstern können die inneren Elemente neu positioniert werden, und die Dimension des div kann sich ändern. Ich frage, ob es möglich ist, das Dimensionsänderungsereignis des Div zu aktivieren. und wie geht das? Derzeit binde ich die Rückruffunktion an das jQuery-Ereignis zur Größenänderung auf dem Ziel-DIV. Es wird jedoch kein Konsolenprotokoll ausgegeben, siehe unten:
<html>
<head>
<script type="text/javascript" language="javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" language="javascript">
$('#test_div').bind('resize', function(){
console.log('resized');
});
</script>
</head>
<body>
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
<input type="button" value="button 1" />
<input type="button" value="button 2" />
<input type="button" value="button 3" />
</div>
</body>
</html>
Es gibt eine sehr effiziente Methode, um festzustellen, ob die Größe eines Elements geändert wurde.
http://marcj.github.io/css-element-queries/
Diese Bibliothek hat eine Klasse ResizeSensor
, die zur Erkennung von Größenänderungen verwendet werden kann.
Es verwendet einen ereignisbasierten Ansatz, ist also verdammt schnell und verschwendet keine CPU-Zeit.
Beispiel:
new ResizeSensor(jQuery('#divId'), function(){
console.log('content dimension changed');
});
Verwenden Sie nicht das jQuery onresize plugin, da es die setTimeout()
-Schleife zur Überprüfung auf Änderungen verwendet.
THIS IS UNGLAUBLICH UND NICHT GENAU.
Offenlegung: Ich bin direkt mit dieser Bibliothek verbunden.
Ein neuer Standard dafür ist das in Chrome 64 verfügbare Resize Observer-API.
function outputsize() {
width.value = textbox.offsetWidth
height.value = textbox.offsetHeight
}
outputsize()
new ResizeObserver(outputsize).observe(textbox)
Width: <output id="width">0</output><br>
Height: <output id="height">0</output><br>
<textarea id="textbox">Resize me</textarea><br>
Spec: https://wicg.github.io/ResizeObserver
Polyfills: https://github.com/WICG/ResizeObserver/issues/3
Firefox Ausgabe: https://bugzil.la/1272409
Safari Ausgabe: http://wkb.ug/157743
Aktueller Support: http://caniuse.com/#feat=resizeobserver
Sie müssen das Ereignis resize
für das Objekt window
und nicht für ein generisches HTML-Element binden.
Sie könnten dann folgendes verwenden:
$(window).resize(function() {
...
});
und innerhalb der Rückruffunktion können Sie die neue Breite Ihres div
-Aufrufs überprüfen
$('.a-selector').width();
Die Antwort auf Ihre Frage ist also nein , Sie können das resize
-Ereignis nicht an ein div binden.
Langfristig können Sie den ResizeObserver verwenden.
new ResizeObserver(callback).observe(element);
Leider wird es derzeit in vielen Browsern nicht standardmäßig unterstützt.
In der Zwischenzeit können Sie die folgenden Funktionen verwenden. Da die meisten Elementgrößenänderungen von der Größenänderung des Fensters oder vom Ändern von Elementen im DOM stammen. Sie können die Größenänderung des Fensters mit dem Ereignis resize des Fensters überwachen und DOM-Änderungen mithilfe von MutationObserver überwachen.
Hier ein Beispiel für eine Funktion, die Sie zurückruft, wenn sich die Größe des bereitgestellten Elements als Ergebnis eines dieser Ereignisse ändert:
var onResize = function(element, callback) {
if (!onResize.watchedElementData) {
// First time we are called, create a list of watched elements
// and hook up the event listeners.
onResize.watchedElementData = [];
var checkForChanges = function() {
onResize.watchedElementData.forEach(function(data) {
if (data.element.offsetWidth !== data.offsetWidth ||
data.element.offsetHeight !== data.offsetHeight) {
data.offsetWidth = data.element.offsetWidth;
data.offsetHeight = data.element.offsetHeight;
data.callback();
}
});
};
// Listen to the window's size changes
window.addEventListener('resize', checkForChanges);
// Listen to changes on the elements in the page that affect layout
var observer = new MutationObserver(checkForChanges);
observer.observe(document.body, {
attributes: true,
childList: true,
characterData: true,
subtree: true
});
}
// Save the element we are watching
onResize.watchedElementData.Push({
element: element,
offsetWidth: element.offsetWidth,
offsetHeight: element.offsetHeight,
callback: callback
});
};
Die beste Lösung wäre die Verwendung der sogenannten Element Queries. Sie sind jedoch kein Standard, es gibt keine Spezifikation - und die einzige Option ist die Verwendung einer der verfügbaren Polyfills/Bibliotheken, wenn Sie auf diese Weise vorgehen möchten.
Die Idee hinter Elementabfragen besteht darin, einem bestimmten Container auf der Seite zu erlauben, auf den ihm zur Verfügung gestellten Speicherplatz zu reagieren. Dadurch können Sie eine Komponente einmal schreiben und dann an einer beliebigen Stelle auf der Seite ablegen, während der Inhalt an die aktuelle Größe angepasst wird. Egal was die Fenstergröße ist. Dies ist der erste Unterschied zwischen Elementabfragen und Medienabfragen. Jeder hofft, dass irgendwann eine Spezifikation erstellt wird, die Elementabfragen (oder etwas, das dasselbe Ziel erreicht) standardisiert und sie nativ, sauber, einfach und robust macht. Die meisten Leute sind sich einig, dass Medienanfragen ziemlich begrenzt sind und nicht für das modulare Design und echte Reaktionsfähigkeit hilfreich sind.
Es gibt ein paar Polyfills/Bibliotheken, die das Problem auf verschiedene Weise lösen (könnte man jedoch auch Problemumgehungen anstelle von Lösungen nennen):
Ich habe andere Lösungen für ähnliche Probleme gesehen. Normalerweise verwenden sie Timer oder die Größe des Fensters/Ansichtsfensters unter der Haube, was keine echte Lösung ist. Darüber hinaus denke ich, dass dies idealerweise hauptsächlich in CSS gelöst werden sollte und nicht in Javascript oder HTML.
Ich fand diese Bibliothek zu funktionieren, wenn MarcJs Lösung nicht funktionierte:
https://github.com/sdecima/javascript-detect-element-resize
Es ist sehr leicht und erkennt sogar natürliche Größenänderungen über CSS oder einfach das Laden/Rendern von HTML.
Codebeispiel (aus dem Link entnommen):
<script type="text/javascript" src="detect-element-resize.js"></script>
<script type="text/javascript">
var resizeElement = document.getElementById('resizeElement'),
resizeCallback = function() {
/* do something */
};
addResizeListener(resizeElement, resizeCallback);
removeResizeListener(resizeElement, resizeCallback);
</script>
Werfen Sie einen Blick auf diese http://benalman.com/code/projects/jquery-resize/examples/resize/
Es hat verschiedene Beispiele. Versuchen Sie, die Fenstergröße zu ändern, und sehen Sie, wie Elemente in Containerelementen angepasst werden.
Beispiel mit js Geige, um zu erklären, wie es funktioniert.
Schauen Sie sich diese Geige an http://jsfiddle.net/sgsqJ/4/
In diesem resize () -Ereignis ist ein Ereignis an ein Element mit der Klasse "test" und auch an das Fensterobjekt Gebunden. In resize () wird der Callback des Fensterobjekts $ ('. Test').
z.B.
$('#test_div').bind('resize', function(){
console.log('resized');
});
$(window).resize(function(){
$('#test_div').resize();
});
ResizeSensor.js ist Teil einer riesigen Bibliothek, aber ich habe die Funktionalität auf THIS reduziert:
function ResizeSensor(element, callback)
{
let zIndex = parseInt(getComputedStyle(element));
if(isNaN(zIndex)) { zIndex = 0; };
zIndex--;
let expand = document.createElement('div');
expand.style.position = "absolute";
expand.style.left = "0px";
expand.style.top = "0px";
expand.style.right = "0px";
expand.style.bottom = "0px";
expand.style.overflow = "hidden";
expand.style.zIndex = zIndex;
expand.style.visibility = "hidden";
let expandChild = document.createElement('div');
expandChild.style.position = "absolute";
expandChild.style.left = "0px";
expandChild.style.top = "0px";
expandChild.style.width = "10000000px";
expandChild.style.height = "10000000px";
expand.appendChild(expandChild);
let shrink = document.createElement('div');
shrink.style.position = "absolute";
shrink.style.left = "0px";
shrink.style.top = "0px";
shrink.style.right = "0px";
shrink.style.bottom = "0px";
shrink.style.overflow = "hidden";
shrink.style.zIndex = zIndex;
shrink.style.visibility = "hidden";
let shrinkChild = document.createElement('div');
shrinkChild.style.position = "absolute";
shrinkChild.style.left = "0px";
shrinkChild.style.top = "0px";
shrinkChild.style.width = "200%";
shrinkChild.style.height = "200%";
shrink.appendChild(shrinkChild);
element.appendChild(expand);
element.appendChild(shrink);
function setScroll()
{
expand.scrollLeft = 10000000;
expand.scrollTop = 10000000;
shrink.scrollLeft = 10000000;
shrink.scrollTop = 10000000;
};
setScroll();
let size = element.getBoundingClientRect();
let currentWidth = size.width;
let currentHeight = size.height;
let onScroll = function()
{
let size = element.getBoundingClientRect();
let newWidth = size.width;
let newHeight = size.height;
if(newWidth != currentWidth || newHeight != currentHeight)
{
currentWidth = newWidth;
currentHeight = newHeight;
callback();
}
setScroll();
};
expand.addEventListener('scroll', onScroll);
shrink.addEventListener('scroll', onScroll);
};
Wie man es benutzt:
let container = document.querySelector(".container");
new ResizeSensor(container, function()
{
console.log("dimension changed:", container.clientWidth, container.clientHeight);
});
Ich empfehle NICHT setTimeout()
hack, da dies die Leistung verlangsamt!!. Stattdessen können Sie DOM-Mutationsbeobachter verwenden, um die Div-Größenänderung zu hören.
JS:
var observer = new MutationObserver(function(mutations) {
console.log('size changed!');
});
var target = document.querySelector('.mydiv');
observer.observe(target, {
attributes: true
});
HTML:
<div class='mydiv'>
</div>
Hier ist die Geige
Versuchen Sie, die Div-Größe zu ändern.
Sie können Ihre Methode in die debounce
-Methode einschließen, um die Effizienz zu verbessern. debounce
löst Ihre Methode alle x Millisekunden aus, anstatt jede Millisekunde auszulösen, an der die DIV geändert wird.
Nur das Fensterobjekt generiert ein Ereignis "Größe ändern". Ich weiß nur, was Sie tun wollen, indem Sie einen Intervall-Timer ausführen, der die Größe regelmäßig überprüft.
Sie können iframe
oder object
mit contentWindow
oder contentDocument
für die Größenänderung verwenden. Ohne setInterval
oder setTimeout
relative
.IFRAME.contentWindow
- onresize
ab<div style="height:50px;background-color:red;position:relative;border:1px solid red">
<iframe style=width:100%;height:100%;position:absolute;border:none;background-color:transparent allowtransparency=true>
</iframe>
This is my div
</div>
Das Javascript:
$('div').width(100).height(100);
$('div').animate({width:200},2000);
$('object').attr({
type : 'text/html'
})
$('object').on('resize,onresize,load,onload',function(){
console.log('ooooooooonload')
})
$($('iframe')[0].contentWindow).on('resize',function(){
console.log('div changed')
})
JsFiddle: https://jsfiddle.net/qq8p470d/
element-resize-event
var div = document.getElementById('div');
div.addEventListener('resize', (event) => console.log(event.detail));
function checkResize (mutations) {
var el = mutations[0].target;
var w = el.clientWidth;
var h = el.clientHeight;
var isChange = mutations
.map((m) => m.oldValue + '')
.some((prev) => prev.indexOf('width: ' + w + 'px') == -1 || prev.indexOf('height: ' + h + 'px') == -1);
if (!isChange)
return;
var event = new CustomEvent('resize', {detail: {width: w, height: h}});
el.dispatchEvent(event);
}
var observer = new MutationObserver(checkResize);
observer.observe(div, {attributes: true, attributeOldValue: true, attributeFilter: ['style']});
#div {width: 100px; border: 1px solid #bbb; resize: both; overflow: hidden;}
<div id = "div">DIV</div>
Mein jQuery-Plugin aktiviert das "resize" -Ereignis für alle Elemente, nicht nur für die window
.
https://github.com/dustinpoissant/ResizeTriggering
$("#myElement") .resizeTriggering().on("resize", function(e){
// Code to handle resize
});
Dieser Blogbeitrag half mir, Größenänderungen an DOM-Elementen effizient zu erkennen.
http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/
So verwenden Sie diesen Code ...
AppConfig.addResizeListener(document.getElementById('id'), function () {
//Your code to execute on resize.
});
Paketcode, der vom Beispiel verwendet wird ...
var AppConfig = AppConfig || {};
AppConfig.ResizeListener = (function () {
var attachEvent = document.attachEvent;
var isIE = navigator.userAgent.match(/Trident/);
var requestFrame = (function () {
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
function (fn) { return window.setTimeout(fn, 20); };
return function (fn) { return raf(fn); };
})();
var cancelFrame = (function () {
var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
window.clearTimeout;
return function (id) { return cancel(id); };
})();
function resizeListener(e) {
var win = e.target || e.srcElement;
if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
win.__resizeRAF__ = requestFrame(function () {
var trigger = win.__resizeTrigger__;
trigger.__resizeListeners__.forEach(function (fn) {
fn.call(trigger, e);
});
});
}
function objectLoad(e) {
this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
this.contentDocument.defaultView.addEventListener('resize', resizeListener);
}
AppConfig.addResizeListener = function (element, fn) {
if (!element.__resizeListeners__) {
element.__resizeListeners__ = [];
if (attachEvent) {
element.__resizeTrigger__ = element;
element.attachEvent('onresize', resizeListener);
} else {
if (getComputedStyle(element).position === 'static') element.style.position = 'relative';
var obj = element.__resizeTrigger__ = document.createElement('object');
obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
obj.__resizeElement__ = element;
obj.onload = objectLoad;
obj.type = 'text/html';
if (isIE) element.appendChild(obj);
obj.data = 'about:blank';
if (!isIE) element.appendChild(obj);
}
}
element.__resizeListeners__.Push(fn);
};
AppConfig.removeResizeListener = function (element, fn) {
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
if (!element.__resizeListeners__.length) {
if (attachEvent) element.detachEvent('onresize', resizeListener);
else {
element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
}
}
}
})();
Hinweis: AppConfig ist ein Namespace/Objekt, das ich zum Organisieren wiederverwendbarer Funktionen verwende. Fühlen Sie sich frei, den Namen durch alles zu ersetzen, was Sie möchten.
Sie können den Code im folgenden Snippet ausprobieren. Er deckt Ihre Bedürfnisse mit einfachem Javascript ab. ( Führen Sie das Code-Snippet aus und klicken Sie auf den Link für die gesamte Seite, um die Warnung auszulösen, dass die Größe des Divs geändert wird, wenn Sie es testen möchten.).
Aufgrund der Tatsache, dass dies eine
setInterval
von 100 Millisekunden ist, würde ich sagen, dass mein PC es nicht zu sehr CPU-hungrig fand. (0,1% der CPU wurden in Chrome zum getesteten Zeitpunkt) als Gesamtmenge für alle geöffneten Tabs verwendet.) Aber auch dies gilt nur für einen Div, wenn Sie dies für einen tun möchten große Menge an Elementen dann könnte es ja sehr CPU-hungrig sein.Sie können jederzeit ein Klickereignis verwenden, um die Größenänderung zu stoppen schnüffeln.
var width = 0;
var interval = setInterval(function(){
if(width <= 0){
width = document.getElementById("test_div").clientWidth;
}
if(document.getElementById("test_div").clientWidth!==width) {
alert('resized div');
width = document.getElementById("test_div").clientWidth;
}
}, 100);
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
<input type="button" value="button 1" />
<input type="button" value="button 2" />
<input type="button" value="button 3" />
</div>
Sie können das Geige auch überprüfen
[~ # ~] Update [~ # ~]
var width = 0;
function myInterval() {
var interval = setInterval(function(){
if(width <= 0){
width = document.getElementById("test_div").clientWidth;
}
if(document.getElementById("test_div").clientWidth!==width) {
alert('resized');
width = document.getElementById("test_div").clientWidth;
}
}, 100);
return interval;
}
var interval = myInterval();
document.getElementById("clickMe").addEventListener( "click" , function() {
if(typeof interval!=="undefined") {
clearInterval(interval);
alert("stopped div-resize sniffing");
}
});
document.getElementById("clickMeToo").addEventListener( "click" , function() {
myInterval();
alert("started div-resize sniffing");
});
<div id="test_div" style="width: 100%; min-height: 30px; border: 1px dashed pink;">
<input type="button" value="button 1" id="clickMe" />
<input type="button" value="button 2" id="clickMeToo" />
<input type="button" value="button 3" />
</div>
Aktualisiert Geige
Mit Clay.js ( https://github.com/zzarcon/clay ) ist es sehr einfach, Änderungen an der Elementgröße zu erkennen:
var el = new Clay('.element');
el.on('resize', function(size) {
console.log(size.height, size.width);
});
Erstaunlicherweise so alt dieses Problem ist, ist dies in den meisten Browsern immer noch ein Problem.
Wie bereits erwähnt wurde, wird Chrome 64+ jetzt nativ mit Resize Observes ausgeliefert. Die Spezifikation wird jedoch immer noch optimiert, und Chrome liegt derzeit (Stand: 29.01.2017) hinter der neuesten Ausgabe der Spezifikation .
Ich habe ein paar gute ResizeObserver-Polyfills in freier Wildbahn gesehen, jedoch folgen einige nicht genau den Spezifikationen, die eng beieinander liegen, und andere haben einige Berechnungsprobleme.
Ich brauchte dieses Verhalten dringend, um responsive Webkomponenten zu erstellen, die in jeder Anwendung verwendet werden können. Damit sie einwandfrei funktionieren, müssen sie ihre Abmessungen zu jeder Zeit kennen. Deshalb klangen ResizeObservers ideal und ich entschied mich für eine Polyfill, die der Spezifikation so genau wie möglich folgte.
Dies ist so ziemlich eine exakte Kopie der obersten Antwort, aber statt eines Links ist es nur der Teil des Codes, der ausschlaggebend ist. Er ist übersichtlich, so dass er IMO besser lesbar und verständlicher ist. Ein paar andere kleine Änderungen beinhalten die Verwendung von cloneNode () und nicht das Einfügen von html in einen js-String. Kleinigkeiten, aber Sie können dies kopieren und einfügen, und es funktioniert.
Die Funktionsweise besteht darin, dass zwei unsichtbare divs das Element, das Sie gerade betrachten, ausfüllen und dann einen Auslöser in jedes Element setzen und eine Bildlaufposition festlegen, die beim Ändern der Größe zu einer Bildlaufänderung führt.
Alles, was Sie wirklich verdienen, geht an Marc J, aber wenn Sie nur nach dem entsprechenden Code suchen, dann hier:
window.El = {}
El.resizeSensorNode = undefined;
El.initResizeNode = function() {
var fillParent = "display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;";
var triggerStyle = "position: absolute; left: 0; top: 0; transition: 0s;";
var resizeSensor = El.resizeSensorNode = document.createElement("resizeSensor");
resizeSensor.style = fillParent;
var expandSensor = document.createElement("div");
expandSensor.style = fillParent;
resizeSensor.appendChild(expandSensor);
var trigger = document.createElement("div");
trigger.style = triggerStyle;
expandSensor.appendChild(trigger);
var shrinkSensor = expandSensor.cloneNode(true);
shrinkSensor.firstChild.style = triggerStyle + " width: 200%; height: 200%";
resizeSensor.appendChild(shrinkSensor);
}
El.onSizeChange = function(domNode, fn) {
if (!domNode) return;
if (domNode.resizeListeners) {
domNode.resizeListeners.Push(fn);
return;
}
domNode.resizeListeners = [];
domNode.resizeListeners.Push(fn);
if(El.resizeSensorNode == undefined)
El.initResizeNode();
domNode.resizeSensor = El.resizeSensorNode.cloneNode(true);
domNode.appendChild(domNode.resizeSensor);
var expand = domNode.resizeSensor.firstChild;
var expandTrigger = expand.firstChild;
var shrink = domNode.resizeSensor.childNodes[1];
var reset = function() {
expandTrigger.style.width = '100000px';
expandTrigger.style.height = '100000px';
expand.scrollLeft = 100000;
expand.scrollTop = 100000;
shrink.scrollLeft = 100000;
shrink.scrollTop = 100000;
};
reset();
var hasChanged, frameRequest, newWidth, newHeight;
var lastWidth = domNode.offsetWidth;
var lastHeight = domNode.offsetHeight;
var onResized = function() {
frameRequest = undefined;
if (!hasChanged) return;
lastWidth = newWidth;
lastHeight = newHeight;
var listeners = domNode.resizeListeners;
for(var i = 0; listeners && i < listeners.length; i++)
listeners[i]();
};
var onScroll = function() {
newWidth = domNode.offsetWidth;
newHeight = domNode.offsetHeight;
hasChanged = newWidth != lastWidth || newHeight != lastHeight;
if (hasChanged && !frameRequest) {
frameRequest = requestAnimationFrame(onResized);
}
reset();
};
expand.addEventListener("scroll", onScroll);
shrink.addEventListener("scroll", onScroll);
}
verwenden Sie Bharat Patil answer, um den maximalen Stapelfehler zu vermeiden. Siehe Beispiel unten:
$('#test_div').bind('resize', function(){
console.log('resized');
return false;
});
Hier ist eine vereinfachte Version der Lösung von @nkron, die auf ein einzelnes Element anwendbar ist (anstelle eines Arrays von Elementen in der Antwort von @nkron, Komplexität, die ich nicht brauchte).
function onResizeElem(element, callback) {
// Save the element we are watching
onResizeElem.watchedElementData = {
element: element,
offsetWidth: element.offsetWidth,
offsetHeight: element.offsetHeight,
callback: callback
};
onResizeElem.checkForChanges = function() {
const data = onResizeElem.watchedElementData;
if (data.element.offsetWidth !== data.offsetWidth || data.element.offsetHeight !== data.offsetHeight) {
data.offsetWidth = data.element.offsetWidth;
data.offsetHeight = data.element.offsetHeight;
data.callback();
}
};
// Listen to the window resize event
window.addEventListener('resize', onResizeElem.checkForChanges);
// Listen to the element being checked for width and height changes
onResizeElem.observer = new MutationObserver(onResizeElem.checkForChanges);
onResizeElem.observer.observe(document.body, {
attributes: true,
childList: true,
characterData: true,
subtree: true
});
}
Der Ereignislistener und -beobachter kann entfernt werden durch:
window.removeEventListener('resize', onResizeElem.checkForChanges);
onResizeElem.observer.disconnect();
Reine Javascript-Lösung, funktioniert aber nur, wenn die Größe des Elements mit der Schaltfläche css resize geändert wird :
offsetWidth
und offsetHeight
mit den gespeicherten Werten. Wenn dies nicht der Fall ist, führen Sie die gewünschten Schritte aus und aktualisieren Sie diese Werte.jQuery(document).ready( function($) {
function resizeMapDIVs() {
// check the parent value...
var size = $('#map').parent().width();
if( $size < 640 ) {
// ...and decrease...
} else {
// ..or increase as necessary
}
}
resizeMapDIVs();
$(window).resize(resizeMapDIVs);
});
Dies ist eine wirklich alte Frage, aber ich dachte mir, ich würde meine Lösung dazu posten.
Ich habe versucht, ResizeSensor
zu verwenden, da jeder ziemlich verknallt zu sein schien. Nach der Implementierung wurde mir jedoch klar, dass unter der Haube der Elementabfrage die Position relative
oder absolute
angewendet werden muss.
Am Ende handelte ich dies mit einem Rxjs interval
anstatt einer geraden setTimeout
oder requestAnimationFrame
wie bei vorherigen Implementierungen.
Das Schöne an der beobachtbaren Variante eines Intervalls ist, dass Sie den Stream ändern können, jedoch auch alle anderen beobachtbaren Werte bearbeitet werden können. Für mich war eine grundlegende Implementierung ausreichend, aber Sie könnten verrückt werden und alle Arten von Zusammenführungen usw. durchführen.
Im folgenden Beispiel verfolge ich die Breitenänderungen des inneren (grünen) Divs. Es hat eine Breite von 50%, aber eine maximale Breite von 200 Pixeln. Durch Ziehen des Schiebereglers wird die Breite des Wrappers (grau) div beeinflusst. Sie können sehen, dass das Observable nur ausgelöst wird, wenn sich die Breite des inneren Bereichs ändert, was nur dann der Fall ist, wenn die Breite des äußeren Bereichs weniger als 400 Pixel beträgt.
const { interval } = rxjs;
const { distinctUntilChanged, map, filter } = rxjs.operators;
const wrapper = document.getElementById('my-wrapper');
const input = document.getElementById('width-input');
function subscribeToResize() {
const timer = interval(100);
const myDiv = document.getElementById('my-div');
const widthElement = document.getElementById('width');
const isMax = document.getElementById('is-max');
/*
NOTE: This is the important bit here
*/
timer
.pipe(
map(() => myDiv ? Math.round(myDiv.getBoundingClientRect().width) : 0),
distinctUntilChanged(),
// adding a takeUntil(), here as well would allow cleanup when the component is destroyed
)
.subscribe((width) => {
widthElement.innerHTML = width;
isMax.innerHTML = width === 200 ? 'Max width' : '50% width';
});
}
function defineRange() {
input.min = 200;
input.max = window.innerWidth;
input.step = 10;
input.value = input.max - 50;
}
function bindInputToWrapper() {
input.addEventListener('input', (event) => {
wrapper.style.width = `${event.target.value}px`;
});
}
defineRange();
subscribeToResize();
bindInputToWrapper();
.inner {
width: 50%;
max-width: 200px;
}
/* Aesthetic styles only */
.inner {
background: #16a085;
}
.wrapper {
background: #ecf0f1;
color: white;
margin-top: 24px;
}
.content {
padding: 12px;
}
body {
font-family: sans-serif;
font-weight: bold;
}
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>
<h1>Resize Browser width</h1>
<label for="width-input">Adjust the width of the wrapper element</label>
<div>
<input type="range" id="width-input">
</div>
<div id="my-wrapper" class="wrapper">
<div id="my-div" class="inner">
<div class="content">
Width: <span id="width"></span>px
<div id="is-max"></div>
</div>
</div>
</div>