当前位置: 首页 > news >正文

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

问题描述:
有个插件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(''); }, []);
http://www.cnnetsun.cn/news/92891.html

相关文章:

  • 云计算作业—-V L AN实验
  • 当连锁巡检“听懂人话”:VLM技术下的智能运营新场景
  • 责任链模式(Chain of Responsibility):实现事件或请求的逐级处理与传递
  • SMUDebugTool深度探索:解锁AMD Ryzen系统的隐藏性能
  • JavaScript 中的单例模式:利用闭包、IIFE 或 ES Modules 实现线程安全的单例
  • CORS 机制中的预检请求(Preflight Request):为什么 OPTIONS 请求总是先于复杂请求发送?
  • Google Drive文件下载终极指南:简单快速解决下载难题
  • 面对一个新领域,如何快速摸清门道?试试“一键生成”研究地图
  • 终极指南:5步实现全球付费内容免费阅读
  • GBase 8s数据库SYSTIMESTAMP表达式介绍(上)
  • 从“秒级”到“毫秒级”:金仓如何让InfluxDB的“时序神话”黯然失色?
  • zotero-style插件深度解析:从零打造高效文献管理生态
  • 5倍推理加速:Axolotl缓存策略如何终结重复计算瓶颈
  • LobeChat能否部署在华为云弹性云服务器?国产化替代实践
  • LobeChat备份与恢复策略:防止重要对话丢失
  • Access Token 生命周期管理:详细设计 Token 的获取、缓存、续期和过期处理机制
  • 客户群 ID 与业务 ID 映射:设计高性能数据库表结构,实现 ChatID 与内部业务标签的快速关联
  • 代码随想录算法训练营Day48 | 108.冗余连接、109.冗余连接II
  • 微信网页版访问困境突破:3步安装wechat-need-web插件实战指南
  • MFC扩展库BCGControlBar Pro v37.1——支持Visual Studio 2026
  • 知乎专题策划:LobeChat是否真的值得入手?
  • 毕业论文AIGC全线飘红?揭秘5个“去AI化”核心手段,附保姆级工具清单
  • MTKClient:如何快速掌握联发科设备调试的核心技巧?
  • 国内云渲染平台有哪些公司?推荐及分析
  • VisualCppRedist AIO:Windows运行库问题的终极免费解决方案
  • 5分钟学会Bypass Paywalls Clean:终极免费阅读指南
  • 音乐播放器插件系统:如何通过5个关键插件实现真正的个性化体验?
  • 什么是“本地永久云手机”,真正独享的云端体验!
  • VMOS Edge与魔云腾Q1对比评测:谁才是本地永久云手机最优选?
  • HC32L130 MCU 片内 OPA(运算放大器)全解析与应用指南