react实现图片预览时截取展示部分图片,不压缩

324 阅读1分钟

react实现图片预览时截取展示部分图片,不压缩

/* eslint-disable react/no-unescaped-entities */
/* eslint-disable react-hooks/exhaustive-deps */
import React, { memo, useEffect, useRef, useState } from 'react';
import { Image } from 'antd';
import styles from './index.less';

const ImageBox = ({ src, width = 184, imgStyle, style }) => {
  const [minHeight, setHeight] = useState(false);
  const [wid, setW] = useState('');
  const myHeight = style?.height?.includes('px') ? style?.height?.replace('px', '') : style.height;
  const imageSize = (url) => {
    const nImg = new window.Image();
    nImg.src = url;
    return new Promise((resolve, reject) => {
      nImg.onload = () => {
        resolve({ success: true, width: nImg.width, height: nImg.height });
      };
      nImg.onerror = () => {
        reject(new Error('imageError'));
      };
    });
  };
  useEffect(() => {
    if (!src) return;
    imageSize(src).then((size) => {
      const { width = 0, height = 1 } = size;
      const proportion = height / width; // 移动端基本上是16:9 或者 16:10
      const h = proportion * (myHeight || 184);
      const w = (myHeight || 184) / proportion;
      if (h < (myHeight || 184)) {
        setHeight(true);
        setW(w);
      } else {
        setHeight(false);
        setW('');
      }
    }); // 失败);
  }, [src]);
  return (
    <div className={styles.imgContainerBox} style={{ width, ...style }}>
      <div
        className={styles.imgContainer}
        style={{
          ...(minHeight && {
            minHeight: myHeight || 184,
            width: wid || width,
            minWidth: width,
          }),
        }}
      >
        <Image
          style={{
            ...imgStyle,
            borderRadius: '4px',
            ...(minHeight && {
              minHeight: myHeight || 184,
              width: wid || width,
              minWidth: width,
            }),
          }}
          src={src}
        />
      </div>
    </div>
  );
};

export default memo(ImageBox);
css样式
.imgContainerBox {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  border-radius: 4px;
  .imgContainer {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    transform: translate(-50%, -50%);
  }
}