generic-zoom-react
Version:
React wrapper of generic-zoom. Medium zoom like functionality, but only transforming the container element. Suited for children that adjust automatically depending on the parent element such as gatsby-image.
122 lines (114 loc) • 5.67 kB
JavaScript
import React, { createContext, useContext, useState, createRef, useEffect } from 'react';
var ZoomContext = createContext({ isZoomed: false, outerElemRef: undefined });
var GenericZoom = function (_a) {
var children = _a.children, isZoomed = _a.isZoomed, outerElemRef = _a.outerElemRef;
// TODO HERE
return (React.createElement("div", { style: { width: 'fit-content' } },
React.createElement(ZoomContext.Provider, { value: { isZoomed: isZoomed, outerElemRef: outerElemRef } }, children)));
};
var GenericZoomOverlay = function () {
return React.createElement("div", null, "I'm an overlay ");
};
var calculateScale = function (outerWidth, outerHeight, innerWidth, innerHeight, margin) {
var scaleX = (outerWidth - 2 * margin.horizontal) / innerWidth;
var scaleY = (outerHeight - 2 * margin.vertical) / innerHeight;
return Math.min(scaleX, scaleY);
};
function calculatePosition(outerElem, elemToZoom) {
var outerRectCenterX = outerElem.clientWidth / 2; // whats difference outerElem.clientWidth and outerRect.left + elemToZoomRect
var outerRectCenterY = outerElem.clientHeight / 2; // originally: const viewportY = window.innerHeight / 2;
var elemToZoomRect = elemToZoom.getBoundingClientRect();
var elemToZoomCenterX = elemToZoomRect.left + elemToZoomRect.width / 2;
var elemToZoomCenterY = elemToZoomRect.top + elemToZoomRect.height / 2;
// Get offset amounts for image coords to be centered on screen
var translateX = outerRectCenterX - elemToZoomCenterX;
var translateY = outerRectCenterY - elemToZoomCenterY;
return { translateX: translateX, translateY: translateY };
}
// /**
// *
// * @param elem element that gets its children transfered to the new element. That new element becomes it's new child.
// */
// export const makeNewInnerElem = (elem: HTMLElement): HTMLElement | null => {
// let newInnerElem: HTMLElement | null;
// if (typeof document === 'undefined') {
// newInnerElem = null;
// } else {
// newInnerElem = document.createElement('div');
// newInnerElem.style.width = '100%';
// newInnerElem.style.height = '100%';
// console.log(elem);
// // transfer elemToZooms children to newElemToZoom
// while (elem.firstChild) {
// console.log(elem.firstChild);
// newInnerElem.appendChild(elem.firstChild);
// elem.removeChild(elem.firstChild);
// }
// elem.appendChild(newInnerElem);
// }
// return newInnerElem;
// };
var GenericZoom$1 = /** @class */ (function () {
function GenericZoom(_a) {
var _b = _a.outerElem, outerElem = _b === void 0 ? typeof document === 'undefined' ? null : document.body : _b, elemToZoom = _a.elemToZoom, elemToZoomWrapper = _a.elemToZoomWrapper, _c = _a.zoomMargin, zoomMargin = _c === void 0 ? { vertical: 50, horizontal: 50 } : _c;
this.outerElem = outerElem;
this.elemToZoomWrapper = elemToZoomWrapper;
this.elemToZoom = elemToZoom;
this.zoomMargin = zoomMargin;
this.applyZoomRef = this.applyZoom.bind(this);
}
GenericZoom.prototype.applyZoom = function () {
if (!this.outerElem || !this.elemToZoom)
return;
var elemToZoomWrapperRect = this.elemToZoomWrapper.getBoundingClientRect();
var _a = calculatePosition(this.outerElem, this.elemToZoomWrapper), translateX = _a.translateX, translateY = _a.translateY;
var scale = calculateScale(this.outerElem.clientWidth, this.outerElem.clientHeight, elemToZoomWrapperRect.width, elemToZoomWrapperRect.height, this.zoomMargin);
this.elemToZoom.style.transition = 'transform 300ms';
this.elemToZoom.style.transform = "translate3d(\n " + translateX + "px,\n " + translateY + "px,\n 0) scale(" + scale + ")";
};
GenericZoom.prototype.zoom = function () {
this.applyZoom();
window.addEventListener('resize', this.applyZoomRef);
};
GenericZoom.prototype.unZoom = function () {
window.removeEventListener('resize', this.applyZoomRef);
if (!this.elemToZoom)
return;
this.elemToZoom.style.transform = "translate3d(\n 0px,\n 0px,\n 0) scale(1)";
};
return GenericZoom;
}());
var GenericZoomContent = function (_a) {
var children = _a.children, _b = _a.zoomMargin;
var _c = useContext(ZoomContext), isZoomed = _c.isZoomed, outerElemRef = _c.outerElemRef;
var _d = useState(null), zoomJS = _d[0], setZoomJS = _d[1];
var elemToZoomWrapperRef = createRef();
var elemToZoomRef = createRef();
useEffect(function () {
var elemToZoom = elemToZoomRef.current;
var elemToZoomWrapper = elemToZoomWrapperRef.current;
var outerElem = outerElemRef && outerElemRef.current;
if (elemToZoom && elemToZoomWrapper) {
setZoomJS(new GenericZoom$1({ outerElem: outerElem, elemToZoom: elemToZoom, elemToZoomWrapper: elemToZoomWrapper }));
}
}, []);
useEffect(function () {
if (isZoomed && zoomJS) {
zoomJS.zoom();
}
if (!isZoomed && zoomJS) {
zoomJS.unZoom();
}
}, [isZoomed, zoomJS]);
return (React.createElement("div", { style: baseStyle, ref: elemToZoomWrapperRef },
React.createElement("div", { style: baseStyle, ref: elemToZoomRef },
children,
isZoomed)));
};
var baseStyle = {
width: 'fit-content',
height: 'fit-content',
};
export default GenericZoom;
export { GenericZoomContent, GenericZoomOverlay };
//# sourceMappingURL=index.es.js.map