Это действительно старый вопрос, но я решил опубликовать свое решение по этому вопросу.
Я пытался использовать, ResizeSensor
так как все, казалось, были в восторге. После реализации, однако, я понял, что под капотом Element Query требуется, чтобы рассматриваемый элемент имел положение relative
илиabsolute
применялся к нему, что не сработало для моей ситуации.
В итоге я обработал это с помощью Rxjs interval
вместо прямой setTimeout
или requestAnimationFrame
аналогичной предыдущей реализации.
Что приятно в наблюдаемой разновидности интервала, так это то, что вы можете модифицировать поток, однако любой другой наблюдаемый может быть обработан. Для меня базовой реализации было достаточно, но вы могли бы сходить с ума и делать всевозможные слияния и т. Д.
В приведенном ниже примере я отслеживаю изменения ширины внутреннего (зеленого) элемента div. Его ширина установлена на 50%, но максимальная ширина составляет 200 пикселей. Перетаскивание ползунка влияет на ширину обёртки (серого) div. Вы можете видеть, что наблюдаемое срабатывает только при изменении ширины внутреннего div, что происходит, только если ширина внешнего div меньше 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>