use-element-fit
Version:
useElementFit is a React hook that allows you to measure and element's based on certain restraints, similar to object-fit in CSS.
107 lines (100 loc) • 4.29 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('use-resize-observer')) :
typeof define === 'function' && define.amd ? define(['exports', 'react', 'use-resize-observer'], factory) :
(global = global || self, factory(global.useElementFit = {}, global.react, global.useResizeObserver));
}(this, function (exports, react, useResizeObserver) { 'use strict';
useResizeObserver = useResizeObserver && useResizeObserver.hasOwnProperty('default') ? useResizeObserver['default'] : useResizeObserver;
var ScaleMode;
(function (ScaleMode) {
ScaleMode["CONTAIN"] = "contain";
ScaleMode["COVER"] = "cover";
ScaleMode["ALIGN_ONLY"] = "align-only";
})(ScaleMode || (ScaleMode = {}));
var ScaleMode$1 = ScaleMode;
const resize = (elementWidth, elementHeight, containerWidth, containerHeight, scaleMode, alignmentX = 0.5, alignmentY = 0.5, maxWidth, maxHeight) => {
let targetWidth = 0;
let targetHeight = 0;
let boundRatioX = 0;
let boundRatioY = 0;
let scale = 1;
// get needed scale to fit in bounds with cover
if (scaleMode === ScaleMode$1.CONTAIN || scaleMode === ScaleMode$1.COVER) {
boundRatioX = containerWidth / elementWidth;
boundRatioY = containerHeight / elementHeight;
}
// get scale for bounds container
switch (scaleMode) {
case ScaleMode$1.CONTAIN:
scale = boundRatioX < boundRatioY ? boundRatioX : boundRatioY;
break;
case ScaleMode$1.COVER:
scale = boundRatioX > boundRatioY ? boundRatioX : boundRatioY;
break;
case ScaleMode$1.ALIGN_ONLY:
targetWidth = elementWidth;
targetHeight = elementHeight;
break;
}
if (scaleMode === ScaleMode$1.CONTAIN || scaleMode === ScaleMode$1.COVER) {
// get needed scale to fit in max with contain
if (maxWidth || maxHeight) {
let scaleMaxRatioX = scale;
let scaleMaxRatioY = scale;
if (maxWidth) {
scaleMaxRatioX = maxWidth / elementWidth;
}
if (maxHeight) {
scaleMaxRatioY = maxHeight / elementHeight;
}
const scaleMax = scaleMaxRatioX < scaleMaxRatioY ? scaleMaxRatioX : scaleMaxRatioY;
scale = Math.min(scale, scaleMax);
}
// do the actual scale
targetWidth = elementWidth * scale;
targetHeight = elementHeight * scale;
}
return {
width: Math.round(targetWidth),
height: Math.round(targetHeight),
x: Math.round((containerWidth - targetWidth) * alignmentX),
y: Math.round((containerHeight - targetHeight) * alignmentY),
};
};
const useElementFit = (width, height, scaleMode = ScaleMode$1.CONTAIN, alignmentX = 0.5, alignmentY = 0.5, maxWidth, maxHeight) => {
const [ref, containerWidth, containerHeight] = useResizeObserver();
const [fitWidth, setFitWidth] = react.useState(1);
const [fitHeight, setFitHeight] = react.useState(1);
const [fitX, setFitX] = react.useState(1);
const [fitY, setFitY] = react.useState(1);
react.useEffect(() => {
const { width: newWidth, height: newHeight, x, y } = resize(width, height, containerWidth, containerHeight, scaleMode, alignmentX, alignmentY, maxWidth, maxHeight);
setFitWidth(newWidth);
setFitHeight(newHeight);
setFitX(x);
setFitY(y);
}, [
containerWidth,
containerHeight,
width,
height,
containerWidth,
containerHeight,
scaleMode,
alignmentX,
alignmentY,
maxWidth,
maxHeight,
]);
return {
ref,
width: fitWidth,
height: fitHeight,
x: fitX,
y: fitY,
};
};
exports.ScaleMode = ScaleMode$1;
exports.useElementFit = useElementFit;
Object.defineProperty(exports, '__esModule', { value: true });
}));
//# sourceMappingURL=index.js.map