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

问题描述:

有个插件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('');
  }, []);
相关推荐
guslegend4 分钟前
脚手架原理与本地调试:从 bin 软链接到 npm link
前端·npm·node.js·脚手架·前端工程化
2601_966949658 分钟前
多市场量化策略的数据接口应该如何设计:从数据层架构到策略接入
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
小宋102111 分钟前
A2UI从零实战:Agent安全生成交互界面与事件回传
javascript·人工智能·安全·交互
坤坤子吖11 分钟前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
奋斗的阿狸_198621 分钟前
ESP32-S3 + ES7210 四通道麦克风录音上传方案
c语言·开发语言·fpga开发
大包子36 分钟前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js
weixin1997010801636 分钟前
《1688图片空间API踩坑:img.upload 与 album.* 的防盗链与CDN缓存问题》(附Python源码)
开发语言·python·缓存
海码事务所37 分钟前
Google Play 新个人开发者账号上架指南:12 人连续 14 天封闭测试怎么做?
前端
田威AI41 分钟前
图片内文字翻译的规格:输入输出、保真、自动化、时间与费用
前端·计算机视觉
ACP广源盛139246256731 小时前
Type‑C 扩展坞方案选型笔记|国产 DP1.4 转 HDMI2.0 桥接芯片 GSV2201S @ACP评估
c语言·开发语言·笔记·硬件架构·硬件工程·国产芯片