UNPKG

@fit-screen/react

Version:

Scale-based large-screen adaptive solution for React Everything is based on the design draft's px size, and the adaptation is done by scale, everything is so simple

343 lines (342 loc) 12.6 kB
(function() { "use strict"; try { if (typeof document != "undefined") { var elementStyle = document.createElement("style"); elementStyle.appendChild(document.createTextNode("body {\n overflow: hidden;\n}\n\n._fit-screen_119nw_5 {\n position: relative;\n height: 100vh;\n width: 100vw;\n}\n._fit-screen_119nw_5._fit_119nw_5, ._fit-screen_119nw_5._full_119nw_10 {\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n._fit-screen_119nw_5._fit_119nw_5 ._fit-screen-scale_119nw_16, ._fit-screen_119nw_5._full_119nw_10 ._fit-screen-scale_119nw_16 {\n transform-origin: center center;\n}\n._fit-screen_119nw_5._scrollY_119nw_19 {\n overflow-x: hidden;\n}\n._fit-screen_119nw_5._scrollY_119nw_19 ._fit-screen-scale_119nw_16 {\n transform-origin: left top;\n}\n._fit-screen_119nw_5._scrollX_119nw_25 {\n overflow-y: hidden;\n}\n._fit-screen_119nw_5._scrollX_119nw_25 ._fit-screen-scale_119nw_16 {\n transform-origin: left top;\n}\n._fit-screen_119nw_5 ._fit-screen-entity_119nw_31 {\n overflow: hidden;\n}")); document.head.appendChild(elementStyle); } } catch (e) { console.error("vite-plugin-css-injected-by-js", e); } })(); var __defProp = Object.defineProperty; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.FitScreen = {}, global.React, global.jsx)); })(this, function(exports2, React, jsxRuntime) { "use strict"; function _interopNamespace(e) { if (e && e.__esModule) return e; var n = /* @__PURE__ */ Object.create(null); if (e) { Object.keys(e).forEach(function(k) { if (k !== "default") { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function() { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var React__namespace = /* @__PURE__ */ _interopNamespace(React); var __defProp2 = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols2 = Object.getOwnPropertySymbols; var __hasOwnProp2 = Object.prototype.hasOwnProperty; var __propIsEnum2 = Object.prototype.propertyIsEnumerable; var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues2 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp2.call(b, prop)) __defNormalProp2(a, prop, b[prop]); if (__getOwnPropSymbols2) for (var prop of __getOwnPropSymbols2(b)) { if (__propIsEnum2.call(b, prop)) __defNormalProp2(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var FitScreenEnum = /* @__PURE__ */ ((FitScreenEnum2) => { FitScreenEnum2["FIT"] = "fit"; FitScreenEnum2["SCROLL_Y"] = "scrollY"; FitScreenEnum2["SCROLL_X"] = "scrollX"; FitScreenEnum2["FULL"] = "full"; return FitScreenEnum2; })(FitScreenEnum || {}); function throttle(func, wait, options) { let timeout, context, args; let previous = 0; if (!options) options = {}; const later = function() { previous = (options == null ? void 0 : options.leading) === false ? 0 : new Date().getTime(); timeout = null; func.apply(context, args); if (!timeout) context = args = null; }; const throttled = function(...rests) { const now = new Date().getTime(); if (!previous && (options == null ? void 0 : options.leading) === false) previous = now; const remaining = wait - (now - previous); context = this; args = rests; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && (options == null ? void 0 : options.trailing)) { timeout = setTimeout(later, remaining); } }; return throttled; } function debounce(func, wait) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { func.apply(this, args); }, wait); }; } const useFitScale = (options) => createCalcRateFn(__spreadProps(__spreadValues2({}, options), { mode: FitScreenEnum.FIT })); const useScrollYScale = (options) => createCalcRateFn(__spreadProps(__spreadValues2({}, options), { mode: FitScreenEnum.SCROLL_Y })); const useScrollXScale = (options) => createCalcRateFn(__spreadProps(__spreadValues2({}, options), { mode: FitScreenEnum.SCROLL_X })); const useFullScale = (options) => createCalcRateFn(__spreadProps(__spreadValues2({}, options), { mode: FitScreenEnum.FULL })); function createCalcRateFn(options) { const { width = 1920, height = 1080, el, mode, executeMode = "throttle", waitTime = 200, beforeCalculate, afterCalculate } = options; let scale = { widthRatio: 1, heightRatio: 1 }; const baseProportion = parseFloat((width / height).toFixed(5)); const calcRate = () => { if (beforeCalculate) { const flag = beforeCalculate(scale); if (flag === false) return; } if (el) { switch (mode) { case FitScreenEnum.FIT: { const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5)); scale = currentRate > baseProportion ? calcRateByHeight(width, height, baseProportion) : calcRateByWidth(width, height, baseProportion); } break; case FitScreenEnum.SCROLL_X: scale = calcRateByHeight(width, height, baseProportion); break; case FitScreenEnum.SCROLL_Y: scale = calcRateByWidth(width, height, baseProportion); break; case FitScreenEnum.FULL: scale = calcRateByStretch(width, height); break; } el.style.transform = `scale(${scale.widthRatio}, ${scale.heightRatio})`; if (afterCalculate) afterCalculate(scale); } }; let tFn = () => { }; switch (executeMode) { case "none": tFn = calcRate; break; case "debounce": tFn = debounce(() => { calcRate(); }, waitTime); break; case "throttle": tFn = throttle(() => { calcRate(); }, waitTime, { trailing: true }); break; default: tFn = throttle(() => { calcRate(); }, waitTime, { trailing: true }); break; } const resize = () => { window.addEventListener("resize", tFn); }; const unResize = () => { window.removeEventListener("resize", tFn); }; return { calcRate, resize, unResize }; } function calcRateByWidth(baseWidth, baseHeight, baseProportion) { const heightRatio = parseFloat((window.innerWidth / baseProportion / baseHeight).toFixed(5)); const widthRatio = parseFloat((window.innerWidth / baseWidth).toFixed(5)); return { widthRatio, heightRatio }; } function calcRateByHeight(baseWidth, baseHeight, baseProportion) { const widthRatio = parseFloat((window.innerHeight * baseProportion / baseWidth).toFixed(5)); const heightRatio = parseFloat((window.innerHeight / baseHeight).toFixed(5)); return { widthRatio, heightRatio }; } function calcRateByStretch(baseWidth, baseHeight) { const widthRatio = parseFloat((window.innerWidth / baseWidth).toFixed(5)); const heightRatio = parseFloat((window.innerHeight / baseHeight).toFixed(5)); return { widthRatio, heightRatio }; } const useFitScreen = (options) => { const entityRef = React__namespace.useRef(null); const previewRef = React__namespace.useRef(null); const { width, height, mode, executeMode, waitTime, onScaleChange } = options; const initFitScreenByMode = () => { let fn; const options2 = { width, height, executeMode, waitTime, el: previewRef.current, beforeCalculate(scale) { const dom = entityRef.current; dom.style.width = `${width * scale.widthRatio}px`; dom.style.height = `${height * scale.heightRatio}px`; }, afterCalculate(scale) { onScaleChange && onScaleChange(scale); } }; switch (mode) { case FitScreenEnum.FIT: fn = useFitScale; delete options2.beforeCalculate; break; case FitScreenEnum.SCROLL_X: fn = useScrollXScale; break; case FitScreenEnum.SCROLL_Y: fn = useScrollYScale; break; case FitScreenEnum.FULL: fn = useFullScale; delete options2.beforeCalculate; break; default: fn = useFitScale; delete options2.beforeCalculate; } return fn(options2); }; React__namespace.useEffect(() => { const { calcRate, resize, unResize } = initFitScreenByMode(); calcRate(); resize(); return () => unResize(); }, [width, height, mode]); return { entityRef, previewRef }; }; const fit = "_fit_119nw_5"; const full = "_full_119nw_10"; const scrollY = "_scrollY_119nw_19"; const scrollX = "_scrollX_119nw_25"; var styles = { "fit-screen": "_fit-screen_119nw_5", fit, full, "fit-screen-scale": "_fit-screen-scale_119nw_16", scrollY, scrollX, "fit-screen-entity": "_fit-screen-entity_119nw_31" }; const InnerFitScreen = React__namespace.forwardRef((props, ref) => { const { width = 1920, height = 1080, mode = "fit", executeMode = "throttle", waitTime = 200, scaleClass, scaleStyle, className, children, onScaleChange } = props; const showEntity = mode === FitScreenEnum.SCROLL_Y || mode === FitScreenEnum.SCROLL_X; const previewRefStyle = [{ position: "relative", width: width ? `${width}px` : "100%", height: height ? `${height}px` : "100%" }, ...Array.isArray(scaleStyle) ? scaleStyle : [scaleStyle]].reduce((style, refStyle) => __spreadValues(__spreadValues({}, style), refStyle), {}); const { previewRef, entityRef } = useFitScreen({ width, height, mode, executeMode, waitTime, onScaleChange }); const scaleDom = /* @__PURE__ */ jsxRuntime.jsx("div", { ref: previewRef, className: `fit-screen-scale ${styles["fit-screen-scale"]}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: scaleClass, style: previewRefStyle, children }) }); const entityDom = /* @__PURE__ */ jsxRuntime.jsx("div", { ref: entityRef, className: `fit-screen-entity ${styles["fit-screen-entity"]}`, children: scaleDom }); return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: `fit-screen ${styles["fit-screen"]} ${styles[mode]} ${className || ""} `, children: showEntity ? entityDom : scaleDom }); }); InnerFitScreen.displayName = "FitScreen"; const FitScreen = React__namespace.memo(InnerFitScreen); var FitScreen$1 = FitScreen; exports2["default"] = FitScreen$1; Object.defineProperty(exports2, "__esModule", { value: true }); });