@fit-screen/vue
Version:
Scale-based large-screen adaptive solution for Vue Everything is based on the design draft's px size, and the adaptation is done by scale, everything is so simple
334 lines (333 loc) • 12.1 kB
JavaScript
(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 FitScreen = function(exports, vueDemi) {
"use strict";
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
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;
};
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(__spreadValues({}, options), { mode: FitScreenEnum.FIT }));
const useScrollYScale = (options) => createCalcRateFn(__spreadProps(__spreadValues({}, options), { mode: FitScreenEnum.SCROLL_Y }));
const useScrollXScale = (options) => createCalcRateFn(__spreadProps(__spreadValues({}, options), { mode: FitScreenEnum.SCROLL_X }));
const useFullScale = (options) => createCalcRateFn(__spreadProps(__spreadValues({}, 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, emit) => {
const entityRef = vueDemi.ref();
const previewRef = vueDemi.ref();
const { width, height, mode, executeMode, waitTime } = vueDemi.toRefs(options);
const initFitScreenByMode = () => {
let fn;
const options2 = {
width: width.value,
height: height.value,
el: previewRef.value,
executeMode: executeMode.value,
waitTime: waitTime.value,
beforeCalculate(scale) {
const dom = entityRef.value;
dom.style.width = `${width.value * scale.widthRatio}px`;
dom.style.height = `${height.value * scale.heightRatio}px`;
},
afterCalculate(scale) {
emit("scaleChange", scale);
}
};
switch (mode.value) {
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);
};
let calcRate, resize, unResize;
vueDemi.watch([width, height, mode], () => {
unResize == null ? void 0 : unResize();
({ calcRate, resize, unResize } = initFitScreenByMode());
calcRate();
resize();
});
vueDemi.onMounted(() => {
({ calcRate, resize, unResize } = initFitScreenByMode());
calcRate();
resize();
});
vueDemi.onUnmounted(() => {
unResize();
});
return {
entityRef,
previewRef
};
};
const realSlot = (defaultSlots) => typeof defaultSlots == "function" ? defaultSlots() : defaultSlots;
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"
};
var FitScreen2 = vueDemi.defineComponent({
name: "FitScreen",
props: {
width: {
type: Number,
default: 1920
},
height: {
type: Number,
default: 1080
},
mode: {
type: String,
default: "fit"
},
executeMode: {
type: String,
default: "throttle"
},
waitTime: {
type: Number,
default: 200
},
scaleClass: {
type: [String, Object, Array],
default: () => []
},
scaleStyle: {
type: [String, Object, Array],
default: () => []
}
},
emits: {
scaleChange(payload) {
const isNumber = (val) => typeof val === "number";
return isNumber(payload.widthRatio) && isNumber(payload.heightRatio);
}
},
setup(props, { emit }) {
const { width, height, mode, scaleStyle } = vueDemi.toRefs(props);
const showEntity = vueDemi.computed(() => {
return mode.value === FitScreenEnum.SCROLL_Y || mode.value === FitScreenEnum.SCROLL_X;
});
const { previewRef, entityRef } = useFitScreen(props, emit);
const previewRefStyle = vueDemi.computed(() => {
return [
{
position: "relative",
width: width.value ? `${width.value}px` : "100%",
height: height.value ? `${height.value}px` : "100%"
},
...Array.isArray(scaleStyle.value) ? scaleStyle.value : [scaleStyle.value]
];
});
return { showEntity, previewRef, entityRef, previewRefStyle };
},
render() {
const previewNode = vueDemi.h(
"div",
{ ref: "previewRef", class: ["fit-screen-scale", styles["fit-screen-scale"]] },
[vueDemi.h("div", { class: this.scaleClass, style: this.previewRefStyle }, realSlot(this.$slots.default))]
);
const entityNode = vueDemi.h("div", { ref: "entityRef", class: ["fit-screen-entity", styles["fit-screen-entity"]] }, [previewNode]);
const resultNode = this.showEntity ? entityNode : previewNode;
return vueDemi.h("div", { class: ["fit-screen", styles["fit-screen"], styles[this.mode]] }, [resultNode]);
}
});
const installFitScreen = (app) => app.component(FitScreen2.name, FitScreen2);
FitScreen2.install = installFitScreen;
if (typeof window !== "undefined" && window.Vue)
window.Vue.use(FitScreen2);
exports["default"] = FitScreen2;
exports.install = installFitScreen;
Object.defineProperty(exports, "__esModule", { value: true });
return exports;
}({}, VueDemi);