UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

68 lines (67 loc) 2.25 kB
/** * Calculates the width/height of the images to fit in the layout. * * Currently does not mutate the cfg.images array, but DOES mutate individual images with .fitWidth, .fitHeight properties. * * @experimental */ export class ImageFitter { constructor(cfg) { this.cfg = { maxHeight: 300, margin: 8, ...cfg, }; this.resizeObserver = new ResizeObserver(entries => this.update(entries)); this.resizeObserver.observe(cfg.containerElement); } cfg; resizeObserver; containerWidth = -1; stop() { this.resizeObserver.disconnect(); } update(entries) { const width = Math.floor(entries[0].contentRect.width); if (width === this.containerWidth) return; // we're only interested in width changes this.containerWidth = width; console.log(`resize ${width}`); this.doLayout(this.cfg.images); this.cfg.onChange(this.cfg.images); } doLayout(imgs) { if (imgs.length === 0) return; // nothing to do const { maxHeight } = this.cfg; let imgNodes = imgs.slice(0); w: while (imgNodes.length > 0) { let slice; let h; for (let i = 1; i <= imgNodes.length; i++) { slice = imgNodes.slice(0, i); h = this.getHeigth(slice); if (h < maxHeight) { this.setHeight(slice, h); imgNodes = imgNodes.slice(i); continue w; } } this.setHeight(slice, Math.min(maxHeight, h)); break; } } getHeigth(images) { const width = this.containerWidth - images.length * this.cfg.margin; let r = 0; images.forEach(img => (r += img.aspectRatio)); return width / r; // have to round down because Firefox will automatically roundup value with number of decimals > 3 } // mutates/sets images' fitWidth, fitHeight properties setHeight(images, height) { images.forEach(img => { img.fitWidth = Math.floor(height * img.aspectRatio); img.fitHeight = Math.floor(height); }); } }