ResizeObserver demo
ResizeObserver for chromestatus
by atotic
HTML
<div id="unavailable">
<h1>ResizeObserver API not available.</h1>
<p>
In Chrome, you can enable it by running chrome with --enable-blink-features=ResizeObserver flag.
</p>
</div>
<section>
<button id="animate">start/stop animation</button>
<button id="grow">grow</button>
<button id="shrink">shrink</button>
</section>
<p>
This is a div, whose content is generated inside a ResizeObserver callback. The callback creates tiles that fill div's content rect.
</p>
<div id="map" class="resize"></div>
CSS
.resize {
border: 20px solid rgba(0,255,0, 0.5);
background-color: #DDD;
width: 300.49px;
height: 200.5px;
overflow: hidden;
position: relative;
display: inline-block;
}
.mapTile {
box-sizing: border-box;
position: absolute;
border-color: yellow;
border-width: 1px;
border-style: solid;
font-size: 24px;
}
#unavailable {
display:none;
color: red;
}
@keyframes resizeAnimationKeyframes {
0% {}
50% {width: 600px;height:300px;}
100% {}
}
.resizeAnimation {
animation-name: resizeAnimationKeyframes;
animation-duration: 4s;
animation-iteration-count: infinite;
}
}
JavaScript
function mapTiles(entry) {
let target = entry.target;
let TileWidth = 100;
let TileHeight = TileWidth * 2 / 3;
let cols = Math.ceil(entry.contentRect.width / TileWidth);
let rows = Math.ceil(entry.contentRect.height / TileHeight);
// Ensure correct number of tiles
let tileCount = cols * rows;
while (target.childNodes.length > tileCount)
target.removeChild(target.firstChild);
while (target.childNodes.length < tileCount)
target.appendChild(document.createElement('div'));
// Position all tiles.
let colWidth = entry.contentRect.width / cols;
let rowHeight = entry.contentRect.height / rows;
for (let r=0; r<rows; r++)
for (let c=0; c<cols; c++) {
let tile = target.childNodes.item(r * cols + c);
tile.innerText = r + "." + c + String.fromCodePoint(0x1F600 + r );
tile.style.left = `${c * colWidth}px`;
tile.style.width = `${colWidth}px`;
tile.style.top = `${r * rowHeight}px`;
tile.style.height = `${rowHeight}px`;
tile.classList.add('mapTile');
}
}
function initUI() {
function resizeBy(delta) {
for (let el of document.querySelectorAll('.resize')) {
let s = window.getComputedStyle(el);
el.style.width = Math.max((parseFloat(s.width) + delta), 10) + 'px';
el.style.height = Math.max((parseFloat(s.height) + delta * 2 / 3), 7) + 'px';
}
}
function animate() {
for (let el of document.querySelectorAll('.resize'))
el.classList.toggle('resizeAnimation');
}
document.querySelector('#grow').addEventListener('click', function() { resizeBy(5) });
document.querySelector('#shrink').addEventListener('click', function() { resizeBy(-5) });
document.querySelector('#animate').addEventListener('click', animate);
// set up resize handler for all maps
document.querySelector('#map').onresize = mapTiles;
}
function initObserver() {
if (!window.ResizeObserver) {
document.querySelector('#unavailable').style.display = "block";
} else {
let ro = new...