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

问题描述:

有个插件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('');
  }, []);
相关推荐
落魄大学生之流水线上谋生计几秒前
GreenLife Carbon · OpenHarmony 智慧低碳生态平台
javascript
wuyk55516 分钟前
【Socket 进阶之路】第 7 章 IO 多路复用 select & poll 完整实战|多 fd 监听、超时等待、优缺点横向对比
服务器·开发语言·网络·数据库·物联网
船厂电气自动化ai大模型24 分钟前
AI大模型与数学|第81天 课程:正交向量、正交基、格拉姆‑施密特(Gram‑Schmidt)正交化
开发语言·数据结构·人工智能·线性代数·机器学习
人工智能培训30 分钟前
大语言模型:从语言理解到通用智能的跃迁
linux·服务器·前端·人工智能
一拳不是超人41 分钟前
做独立开发三个月,我的第一个产品终于有了 1000 个用户
前端·程序员
Amos_Web1 小时前
Rspack 源码解析(十):Hash 与 Asset 生成
前端·rust·源码阅读
福兮说1 小时前
用 IndexedDB 存用户的文件,我踩过的五个坑
前端·javascript
闪耀之光M781 小时前
前端依赖自动导入:unplugin-auto-import
前端
lv__pf1 小时前
seata【实战 msb】
java·开发语言·后端
点纭1 小时前
C 语言 第七章 常用函数(3)
c语言·开发语言·算法·oracle·c#