Esta es una pregunta muy antigua, pero pensé que publicaría mi solución a esto.
Traté de usarlo ResizeSensor
ya que todo el mundo parecía estar bastante enamorado de él. Sin embargo, después de implementar, me di cuenta de que, bajo el capó, la consulta de elementos requiere que el elemento en cuestión tenga una posición relative
o se le absolute
aplique, lo que no funcionó para mi situación.
Terminé manejando esto con un Rxjs en interval
lugar de una implementación anterior directa setTimeout
o requestAnimationFrame
similar.
Lo bueno del sabor observable de un intervalo es que puedes modificar la transmisión, sin embargo, cualquier otro observable puede ser manejado. Para mí, una implementación básica era suficiente, pero podría volverse loco y hacer todo tipo de fusiones, etc.
En el siguiente ejemplo, estoy rastreando los cambios de ancho del div (verde) interno. Tiene un ancho establecido en 50%, pero un ancho máximo de 200 px. Al arrastrar el control deslizante, se afecta el ancho del contenedor (gris) div. Puedes ver que lo observable solo se dispara cuando cambia el ancho del div interno, lo que solo sucede si el ancho del div externo es menor que 400px.
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>