图片根据自身宽高比进行容器自适应,以及图片上的元素根据图片变化相对位置不改变

当图片根据宽高比进行伸缩时,图片是最清晰的

代码示例:

import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { Intl } from '@/components/Intl/index';
import style from './index.less';
import { MyIcon } from '../IconFont';
import { IStep } from '../../configs/guide-options';

interface IProps {
  isShowGuide: boolean;
  onShowGuideHandler: () => void;
  guideOptions: (imgRatio: { x: number; y: number }) => IStep;
}

type Props = IProps;

export default function NewGuidelines(props: Props) {
  const { isShowGuide, onShowGuideHandler, guideOptions } = props;
  const [currentStep, setCurrentStep] = useState(0);
  
  //图片缩放比
  const [imgRatio, setImgRatioRatio] = useState({ x: 1, y: 1 });	
  //图片大小
  const [imgSize, setImgSize] = useState({ width: '1440', height: '900' });

  useEffect(() => {
    if (!isShowGuide) {
      setCurrentStep(0);
    }
  }, [isShowGuide]);
	
  //监听屏幕变化
  useEffect(() => {
    if (isShowGuide) {
      autoResize();
      window.addEventListener('resize', autoResize);
    } else {
      window.removeEventListener('resize', autoResize);
    }

    return () => {
      window.removeEventListener('resize', autoResize);
    };
  }, [isShowGuide]);

  const stepHandler = useCallback(() => {
    let tempCurrentStep = currentStep + 1;
    if (tempCurrentStep === 8) {
      tempCurrentStep = 7;
      onShowGuideHandler();
    }
    setCurrentStep(tempCurrentStep);
  }, [currentStep, onShowGuideHandler]);
  
  //进行自适应
  const autoResize = useCallback(
    (event?, naturalWidth = 1440, naturalHeight = 900) => {
      //获取原始图片宽高比,未知情况下可使用naturalWidth|naturalHeight获取
      const scale = naturalHeight / naturalWidth;
      //获取视口大小
      const clientHeight = document.documentElement.clientHeight;
      const clientWidth = document.documentElement.clientWidth;

      let imgWidth;
      let imgHeight;
      //当视口宽度大于高度时,图片高度占满,宽度根据缩放比自适应
      if (clientWidth > clientHeight) {
        imgHeight = clientHeight;
        imgWidth = clientHeight / scale;
        imgWidth = Math.min(clientWidth, imgWidth);
      } else {
      //当视口宽度小于高度时,图片宽度占满,高度根据缩放比自适应
        imgWidth = clientWidth;
        imgHeight = clientWidth * scale;
        imgHeight = Math.min(clientHeight, imgHeight);
      }
	  
	  //获取图片伸缩后,和原始图片高宽的比例
      let imgRatioX = imgWidth / naturalWidth;
      let imgRationY = imgHeight / naturalHeight;
	  
	  //获取到图片伸缩后和原始图片高宽的比例,就能使得定位在图片上的其他元素,也根据图片变化,即伸缩相对位置不改变
      setImgRatioRatio({ x: imgRatioX, y: imgRationY });
      setImgSize({ width: imgWidth, height: imgHeight });
    },
    []
  );

  const stepOptions = useMemo(() => guideOptions(imgRatio), [imgRatio]);

  const GuideModel = () => {
    return (
      <div
        className={style.guidemodel}
        style={stepOptions[currentStep].boxPosition}
      >
        <div className={style.guideTitle}>
          <span>{stepOptions[currentStep].title}</span>
          <span
            onClick={() => {
              onShowGuideHandler();
            }}
            style={{ cursor: 'pointer' }}
          >
            <MyIcon type="icon-a-01_line1" />
          </span>
        </div>

        <div className={style.guideDesc}>
          <span>{stepOptions[currentStep].text}</span>
        </div>

        <div className={style.guideFooter}>
          <div className={style.guideFooterLeft}>
            <div className={style.guideFooterCount}>{currentStep + 1}/8</div>
            <div className={style.guideFooterDotted}>
              {stepOptions.map((item, index) => (
                <div
                  key={item.text}
                  className={`${
                    currentStep === index && style.guideFooterDottedActive
                  }`}
                />
              ))}
            </div>
          </div>
          <div className={style.guideFooterBtn} onClick={stepHandler}>
            下一步
          </div>
        </div>
      </div>
    );
  };

  return (
    <div
      className={style.guide}
      style={{ display: isShowGuide ? 'block' : 'none' }}
    >
      <div className={style.guideContainer}>
      	//设置图片大小
        <div
          className={style.imgbg}
          style={{ width: `${imgSize.width}px`, height: `${imgSize.height}px` }}
        >
          <img src={stepOptions[currentStep].imgUrl} alt="" />
          <GuideModel />
        </div>
      </div>
    </div>
  );
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值