react中封装组件对三方库或者已有ui组件进行自动调整大小嵌入显示区域

原因:有些三方库的组件或者已有的组件ui部分无法调整大小,比如组件是全屏覆盖显示但是在新开发的迭代要求缩小到部分区域显示

解决方法:使用css的属性transform scale,通过绝对定位处理放大或者缩小的处理区域

ini 复制代码
import React, {
  FC, useEffect, useRef, useState,
} from 'react';
import { useSize } from 'ahooks';
import { isEmpty, min } from 'lodash';
import { css } from '@emotion/css';

interface Props {
  debug?: boolean
  lockMaxWidth?: boolean
  lockMaxHeight?: boolean
}

export const AutoScale: FC<React.PropsWithChildren & Props> = ({ children, debug, lockMaxHeight = true, lockMaxWidth = true }) => {
  const outsideWrapperRef = useRef<HTMLDivElement>(null);
  const insideWrapperRef = useRef<HTMLDivElement>(null);
  const outsideSize = useSize(outsideWrapperRef.current?.parentElement);
  const insideSize = useSize(insideWrapperRef);
  const [scale, setScale] = useState(1);
  const [height, setHeight] = useState(0);
  const [width, setWidth] = useState(0);

  useEffect(() => {
    if (isEmpty(insideSize) || isEmpty(outsideSize)) {
      return;
    }
    if (debug) {
      console.log(outsideSize);
    }

    const scaleWidth = outsideSize.width / insideSize.width;
    const scaleHeight = outsideSize.height / insideSize.height;
    let resultScale;

    switch (true) {
      case lockMaxWidth && !lockMaxHeight:
        resultScale = scaleWidth;
        break;
      case !lockMaxWidth && lockMaxHeight:
        resultScale = scaleHeight;
        break;
      case lockMaxWidth && lockMaxHeight:
        resultScale = min([scaleWidth, scaleHeight]);
        break;
      default:
        resultScale = scaleWidth;
        break;
    }

    setScale(resultScale);
    setHeight(insideSize.height * resultScale);
    setWidth(insideSize.width * resultScale);
  }, [insideSize, outsideSize]);

  return (
    <div
      ref={outsideWrapperRef}
      className={css`
          position: relative;
          width: ${`${width}px` || '100%'};
          height: ${`${height}px` || '100%'};
          overflow: ${width ? 'initial' : 'hidden'};
      `}
    >
      <div
        ref={insideWrapperRef}
        className={css`
          position: absolute;
          top: 0;
          left: 0;
          transform-origin: left top;
          transform: scale(${scale});
      `}
      >
        {children}
      </div>
    </div>
  );
};
相关推荐
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
用户298698530141 天前
在 React 中用 JavaScript 将 Word 转换为文本
前端·javascript·react.js
狗狗狗狗狗乐啊2 天前
搭一个 AI 对话工作台 AChat:从 0 到可用的完整记录(一)
python·react.js·ai编程
晓得迷路了2 天前
栗子前端技术周刊第 147 期 - React Router 8.4、Vite 云服务攻击、pnpm 12.4...
前端·javascript·react.js
神秘的猪头3 天前
React 脱围机制(二):重新理解 useEffect——它不是生命周期,而是同步外部系统
react.js
卡布鲁3 天前
React useMemo 与 useCallback 完全指南:原理、场景与避坑
前端·react.js
右耳朵猫AI3 天前
Web前端周刊2026W38 | React 19.3 发布、StyleX 深潜、jsdom 30.1 提速
前端·javascript·react.js·typescript·node.js
晚安日记wanna4 天前
React 为何不做双端 diff?Vue 与 React 更新逻辑的三层差异
前端·react.js·面试
光影少年4 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
用户298698530145 天前
前端如何把 TXT 文本文件转成 Word 文档:React 实践
前端·javascript·react.js