前端自适应布局之等比例缩放

问题描述:

有个插件Postcss-pxtorem能自动转换px做适配,但是某些插件不能转换,例如antd。

设计图只有一套1920*1080.要做到尽量1比1还原,又能适配大小屏幕,如果一个个转百分比会非常麻烦。

这时就可以选择用等比例缩放实现自适应布局。
运行环境 :react+umi(其他也可用,原理一样)

1.根据设计图1比1写px。

2.在layout写

复制代码
import React, { useEffect, useRef, useState } from 'react';
import { Outlet } from '@umijs/max';
import styles from './ScaleLayout.less';
import { LayoutProvider } from './context';

const ScaleLayout: React.FC = () => {
  const [bg, setBgState] = useState('');

  const scaleRootRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const setScale = () => {
      const scaleX = window.innerWidth / 1920;
      const scaleY = window.innerHeight / 1080;
      // Use Math.min to fit the screen while maintaining aspect ratio (letterboxing)
      const scale = Math.min(scaleX, scaleY);
      console.log('scale', scale);

      if (scaleRootRef.current) {
        scaleRootRef.current.style.transform = `scale(${scale})`;
      }
    };

    // Initial scale
    setScale();
    
    // Add event listener
    window.addEventListener('resize', setScale);
    
    // Cleanup
    return () => window.removeEventListener('resize', setScale);
  }, []);

  return (
    <LayoutProvider value={{ setBg: setBgState }}>
      <div className={styles.viewport}>
        <div className={styles.pageBg} style={{ backgroundImage: bg ? `url(${bg})` : 'none' }} />
        <div className={styles.scaleRoot} ref={scaleRootRef}>
          <Outlet />
        </div>
      </div>
    </LayoutProvider>
  );
};

export default ScaleLayout;

layout样式:

复制代码
.viewport {
  width: 100vw;
  height: 100vh;
  background: #050b16; // Match the app's dark theme
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
}
/* 页面背景层(不参与缩放) */
.pageBg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  z-index: 0;

}
.scaleRoot {
  width: 1920px;
  height: 1080px;
  transform-origin: center center;
  flex-shrink: 0;
  overflow: hidden;
}

背景有黑边?把背景提到缩放盒子外边。这样就能实现内容的1比1,又不会太难看。

context.tsx

复制代码
import React, { createContext, useContext, useState } from 'react';

interface LayoutContextType {
  setBg: (bg: string) => void;
}

const LayoutContext = createContext<LayoutContextType | undefined>(undefined);

export const useLayout = () => {
  const context = useContext(LayoutContext);
  if (!context) {
    throw new Error('useLayout must be used within a LayoutProvider');
  }
  return context;
};

export const LayoutProvider: React.FC<{ children: React.ReactNode; value: LayoutContextType }> = ({ children, value }) => {
  return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>;
};

页面设置背景

复制代码
import { useLayout } from '@/layouts/context';
import bg from '@/assets/imgs/training/zice/learn_sel_bg.png'
const { setBg } = useLayout();
  useEffect(() => {
    setBg(bg);
    return () => setBg('');
  }, []);
相关推荐
caimouse27 分钟前
reactos编码规范
c语言·开发语言
小雨下雨的雨2 小时前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.4 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
CryptoPP5 小时前
快速对接东京证券交易所API数据:实战指南与代码示例
开发语言·人工智能·windows·python·信息可视化·区块链
ZC跨境爬虫6 小时前
跟着 MDN 学JavaScript day_7:数学运算与逻辑判断实战测试
开发语言·前端·javascript·学习·ecmascript
fangdengfu1236 小时前
ES分析系统各个服务日志占用量
java·前端·elasticsearch
凌云拓界6 小时前
文件管理:让AI安全操作你的电脑 ——CogitoAgent开发实战(三)
javascript·人工智能·架构·开源·node.js
凌云拓界6 小时前
联网能力:让AI看见更广阔的世界 ——CogitoAgent开发实战(四)
javascript·人工智能·架构·node.js·创业创新
阳区欠7 小时前
【LangChain】LLM基础介绍
开发语言·python·langchain
Jinkxs7 小时前
Java 跨域14-Java 与区块链(Hyperledger)集成
java·开发语言·区块链