95 lines
2.3 KiB
TypeScript
95 lines
2.3 KiB
TypeScript
import { useEffect, useState, useMemo } from "react";
|
|
|
|
/**
|
|
* 等比例缩放Hook
|
|
* 基于1920*1080设计稿进行等比例缩放
|
|
*/
|
|
export function usePageScale() {
|
|
// 设计稿尺寸
|
|
const DESIGN_WIDTH = 1920;
|
|
const DESIGN_HEIGHT = 1080;
|
|
|
|
// 当前窗口尺寸
|
|
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
|
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
|
|
|
// 是否移动端竖屏(需要旋转横屏展示)
|
|
const isMobilePortrait = useMemo(() => {
|
|
const ua = window.navigator.userAgent.toLowerCase();
|
|
const isMobile = /iphone|ipad|ipod|android|mobile/.test(ua);
|
|
return isMobile && windowHeight > windowWidth;
|
|
}, [windowHeight, windowWidth]);
|
|
|
|
// 缩放比例
|
|
const scale = useMemo(() => {
|
|
const baseWidth = DESIGN_WIDTH;
|
|
const baseHeight = DESIGN_HEIGHT;
|
|
const scaleX = windowWidth / baseWidth;
|
|
const scaleY = windowHeight / baseHeight;
|
|
return Math.min(scaleX, scaleY);
|
|
}, [windowWidth, windowHeight]);
|
|
|
|
// 缩放后的实际尺寸
|
|
const scaledWidth = useMemo(() => DESIGN_WIDTH * scale, [scale]);
|
|
const scaledHeight = useMemo(() => DESIGN_HEIGHT * scale, [scale]);
|
|
|
|
// 居中偏移量
|
|
const offsetX = useMemo(
|
|
() => (windowWidth - scaledWidth) / 2,
|
|
[windowWidth, scaledWidth]
|
|
);
|
|
const offsetY = useMemo(
|
|
() => (windowHeight - scaledHeight) / 2,
|
|
[windowHeight, scaledHeight]
|
|
);
|
|
|
|
// 缩放样式对象
|
|
const scaleStyle = useMemo(
|
|
() => ({
|
|
position: "absolute" as const,
|
|
width: `${DESIGN_WIDTH}px`,
|
|
height: `${DESIGN_HEIGHT}px`,
|
|
left: `${offsetX}px`,
|
|
top: `${offsetY}px`,
|
|
transform: `scale(${scale})`,
|
|
transformOrigin: "top left",
|
|
}),
|
|
[scale, offsetX, offsetY]
|
|
);
|
|
|
|
// 更新窗口尺寸
|
|
const updateWindowSize = () => {
|
|
setWindowWidth(window.innerWidth);
|
|
setWindowHeight(window.innerHeight);
|
|
};
|
|
|
|
// 监听窗口大小变化
|
|
useEffect(() => {
|
|
window.addEventListener("resize", updateWindowSize);
|
|
updateWindowSize();
|
|
|
|
return () => {
|
|
window.removeEventListener("resize", updateWindowSize);
|
|
};
|
|
}, []);
|
|
|
|
return {
|
|
// 响应式数据
|
|
windowWidth,
|
|
windowHeight,
|
|
scale,
|
|
scaledWidth,
|
|
scaledHeight,
|
|
offsetX,
|
|
offsetY,
|
|
|
|
// 样式对象
|
|
scaleStyle,
|
|
isMobilePortrait,
|
|
|
|
// 常量
|
|
DESIGN_WIDTH,
|
|
DESIGN_HEIGHT,
|
|
};
|
|
}
|