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

问题描述:

有个插件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('');
  }, []);
相关推荐
Wenweno0o1 天前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
于慨1 天前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz1 天前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶1 天前
前端交互规范(Web 端)
前端
@yanyu6661 天前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
CHU7290351 天前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
chenjingming6661 天前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
GISer_Jing1 天前
Page-agent MCP结构
前端·人工智能
王霸天1 天前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航1 天前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github