Heim  >  Artikel  >  Web-Frontend  >  So implementieren Sie die Skalierung in React

So implementieren Sie die Skalierung in React

藏色散人
藏色散人Original
2022-12-28 10:13:072297Durchsuche

So implementieren Sie die Skalierung in React: 1. Hören Sie sich das onWheel-Ereignis an. 2. Legen Sie das Attribut deltaY des Ereignisobjekts fest, „deltaY0“, wenn Sie nach unten scrollen. Ändern Sie jeden Bildlauf. Beim Skalieren können Sie den Transformationsstil ändern, um ihn entsprechend zu skalieren.

So implementieren Sie die Skalierung in React

Die Betriebsumgebung dieses Tutorials: Windows 10-System, Reaktionsversion 18.0.0, Dell G3-Computer.

Wie implementiert man die Skalierung in React?

Reagieren Sie auf das Zoomen und Schwenken von Bildern (Position, Transformationsimplementierung)

Viele Webseiten hängen einige Bilder an, um die Beschreibung der Kopie zu ergänzen. Wenn beispielsweise über die Adresse gesprochen wird, wird daneben eine Karte angehängt , und auf der Karte Markieren Sie diese Adresse. Wenn das angehängte Bild sehr klein ist und es schwierig ist, die spezifischen Informationen der Adresse klar zu erkennen, entwickeln einige Produktmanager eine Funktion zum Schwenken, Vergrößern und Verkleinern des Bildes. In diesem Artikel werden die oben genannten Funktionen einzeln implementiert. 🔜 : onMouseDown, onMouseMove, onMouseUp. Das Ereignis
onMouseDown zeichnet die Koordinatenposition jedes Mausklicks auf; das Ereignis
onMouseMove berechnet den Abstand jeder Verschiebung und den Abstand plus Ziehen Das vorherige Bild und das übergeordnete Element entsprechen dem Abstand zwischen dem gezogenen Bild und dem übergeordneten Element;
onMouseUpWenn das Ereignis ausgelöst wird, melden Sie sich ab oder verhindern Sie die Ausführung vononMouseDown, onMouseMoveEreignis, um zu verhindern, dass das Bild geschwenkt wird, wenn die Maus hinein bewegt wird.

Diese drei Ereignisse müssen das Standardverhalten des Browsers verhindern, sonst wird das Bild beim Verschieben automatisch geöffnet.
So implementieren Sie die Skalierung in React

const WIDTH = 1200;const HEIGHT = 900;const DynamicStyle= () => {    
  const imgRef = React.createRef<HTMLImageElement>();  
  /** 图片样式 */  const [imgStyle, setImgStyle] = useState<React.CSSProperties>({});  /** 记录鼠标是否按下 */  const [mouseDowmFlag, setMouseDowmFlag] = useState(false);  /** 记录鼠标按下的坐标 */  const [mouseDowmPos, setMouseDowmPos] = useState<{x: number, y: number}>({x: 0, y: 0})  /** 鼠标可视区域时,重置鼠标按下的布尔值为false */  useEffect(() => {    document.onmouseover = () => {      if (mouseDowmFlag) {        setMouseDowmFlag(false);
      }
    };    return () => {      document.onmouseover = null;
    };
  }, [mouseDowmFlag])  /** 平移 */  const handleMouseDown = (event: React.MouseEvent<HTMLImageElement>) => {    const { clientX, clientY } = event;
    event.stopPropagation();
    event.preventDefault(); // 阻止浏览器默认行为,拖动会打开图片    setMouseDowmFlag(true); // 控制只有在鼠标按下后才会执行mousemove    setMouseDowmPos({      x: clientX,      y: clientY,
    });
  };  const handleMouseMove = (event: React.MouseEvent<HTMLImageElement>) => {
    event.stopPropagation();
    event.preventDefault();    const { clientX, clientY } = event;    const diffX = clientX - mouseDowmPos.x;    const diffY = clientY - mouseDowmPos.y;    if (!mouseDowmFlag || (diffX === 0 && diffY === 0)) return;    const { offsetLeft, offsetTop } = imgRef.current as HTMLImageElement;    const offsetX = parseInt(`${diffX + offsetLeft}`, 10);    const offsetY = parseInt(`${diffY + offsetTop}`, 10);    setMouseDowmPos({      x: clientX,      y: clientY,
    });    setImgStyle({
      ...imgStyle,      left: offsetX,      top: offsetY,
    });
  };  const handleMouseUp = (event: React.MouseEvent<HTMLImageElement>) => {
    event.stopPropagation();
    event.preventDefault();    setMouseDowmFlag(false);
  };  return (    <div className={styles.imgArea}>      <img 
        src={mapImg} 
        alt=&#39;part&#39;        ref={imgRef}        height={HEIGHT} 
        style={imgStyle}        onMouseDown={handleMouseDown}        onMouseMove={handleMouseMove}        onMouseUp={handleMouseUp}
      >      </img>    </div>
  )
}

Picture zoomSo implementieren Sie die Skalierung in React

Picture zoom kann auf das Ereignis onWheel hören. Das Ereignisobjekt event hat ein Attribut deltaY, das das Scrollrad aufzeichnet. Beim Scrollen nach oben deltaY, <code>deltaY>0 beim Scrollen nach unten. Bei jedem Scrollen ändert sich das Skalierungsverhältnis und der transform-Stil wird entsprechend angepasst.

So implementieren Sie die Skalierung in React
    const WIDTH = 1200;const HEIGHT = 900;const SCALE = 0.2;const DynamicStyle= () => {  const imgRef = React.createRef<HTMLImageElement>();  /** 初始化缩放比例,默认为1 */  const [rate, setRate] = useState(1);  /** 图片样式 */  const [imgStyle, setImgStyle] = useState<React.CSSProperties>({});  /** 记录鼠标是否按下 */  const [mouseDowmFlag, setMouseDowmFlag] = useState(false);  /** 记录鼠标按下的坐标 */  const [mouseDowmPos, setMouseDowmPos] = useState<{x: number, y: number}>({x: 0, y: 0})  /** 图片现在大小 */  const [initial, setInitial] = useState<{width: number, height: number}>({width: WIDTH, height: HEIGHT});  useEffect(() => {    const { naturalWidth, naturalHeight, width, height } = imgRef.current as HTMLImageElement;    setInitial({ width, height });    // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [])  // console.log(natural, initial)  useEffect(() => {    document.onmouseover = () => {      if (mouseDowmFlag) {        setMouseDowmFlag(false);
          }
        };    return () => {      document.onmouseover = null;
        };
      }, [mouseDowmFlag])  /** 缩放 */  const handleWheelImage = (event: React.WheelEvent<HTMLImageElement>) => {    // 向上为负,向下为正    const bigger = event.deltaY > 0 ? -1 : 1;    // transform偏移量    const transformX = -initial.width / 2;    const transformY = -initial.height / 2;    if (bigger > 0 && rate < 2) {      const enlargeRate = rate + SCALE;      setImgStyle({
            ...imgStyle,        transform: `matrix(${enlargeRate}, 0, 0, ${enlargeRate}, ${transformX}, ${transformY})`, // 默认以图片中心为原点进行缩放
          });      setRate(enlargeRate);
        } else if (bigger < 0 && rate > 1) {      const shrinkRate = rate - SCALE;      setImgStyle({
            ...imgStyle,        transform: `matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})`,
          });      setRate(shrinkRate);
        }
      }  /** 平移 */  const handleMouseDown = (event: React.MouseEvent<HTMLImageElement>) => {    const { clientX, clientY } = event;
        event.stopPropagation();
        event.preventDefault(); // 阻止浏览器默认行为,拖动会打开图片    setMouseDowmFlag(true); // 控制只有在鼠标按下后才会执行mousemove    setMouseDowmPos({      x: clientX,      y: clientY,
        });
      };  const handleMouseMove = (event: React.MouseEvent<HTMLImageElement>) => {
        event.stopPropagation();
        event.preventDefault();    const { clientX, clientY } = event;    const diffX = clientX - mouseDowmPos.x;    const diffY = clientY - mouseDowmPos.y;    if (!mouseDowmFlag || (diffX === 0 && diffY === 0)) return;    const { offsetLeft, offsetTop } = imgRef.current as HTMLImageElement;    const offsetX = parseInt(`${diffX + offsetLeft}`, 10);    const offsetY = parseInt(`${diffY + offsetTop}`, 10);    setMouseDowmPos({      x: clientX,      y: clientY,
        });    setImgStyle({
          ...imgStyle,      left: offsetX,      top: offsetY,
        });
      };  const handleMouseUp = (event: React.MouseEvent<HTMLImageElement>) => {
        event.stopPropagation();
        event.preventDefault();    setMouseDowmFlag(false);
      };  return (    <div className={styles.imgArea}>      <img 
            src={mapImg} 
            alt=&#39;part&#39; 
            height={HEIGHT} 
            style={imgStyle}        ref={imgRef}        onWheel={handleWheelImage}        onMouseDown={handleMouseDown}        onMouseMove={handleMouseMove}        onMouseUp={handleMouseUp}
          >      </img>    </div>
      )
    }
    .imgArea {  position: relative;  width: 1200px;  height: 900px;  margin: auto;  border: 1px solid #da2727;  overflow: hidden;
      & > img {    position: absolute;    left: 50%;    top: 50%;    transform: translate(-50%, -50%);    cursor: move;
      }
    }
  • Wenn transformOrigin nicht festgelegt ist, wird standardmäßig relativ zur Bildmitte skaliert, zunächst jedoch, um das Bild horizontal und vertikal im sichtbaren Bereich zu zentrieren, transform: Translate(- 50 %, - 50 %);. Um also relativ zum Mittelpunkt des Bildes zu skalieren, müssen Sie den fünften und sechsten Parameter von matrix so einstellen, dass korrigiert wird transformOrigin, transform : matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})
  • Stationsbezeichnung
  • Zuerst definieren eine Konstante zur Darstellung der Koordinaten des Symbols. Diese Koordinate wird relativ zur oberen linken Ecke des Originalbilds positioniert.
  • const imgInfo = {  lableLeft: "1900",  lableTop: "2000",}
Erklären Sie hier das Konzept des Originalbilds:
So implementieren Sie die Skalierung in React

Schauen Sie sich einfach ein Bildelement im Internet an, wie das oben. 1200 x 900 ist die auf der Seite angegebene Bildgröße, das Bild hat jedoch auch eine tatsächliche Größe von 4535 x 3402.

onMouseDown、onMouseMove、onMouseUp
onMouseDown事件记录每次鼠标按下的坐标位置;
onMouseMove事件计算出每次平移的距离,该距离加上拖动前图片距离父元素的距离就等于拖动后图片相对于父元素的距离;
onMouseUp事件触发时,注销或者不让执行onMouseDown、onMouseMove事件,防止只要鼠标移入图片就会平移。

这三个事件需要阻止浏览器的默认行为,不然在移动时会自动打开图片。
So implementieren Sie die Skalierung in React

/** 图片原始大小,默认设置为1是防止计算图片原始大小与初始大小比例出现无穷大 */const [natural, setNatural] = useState<{width: number, height: number}>({width: 1, height: 1});/** 图片现在大小 */const [initial, setInitial] = useState<{width: number, height: number}>({width: WIDTH, height: HEIGHT});useEffect(() => {    const { naturalWidth, naturalHeight, width, height } = imgRef.current as HTMLImageElement;    setNatural({ width: naturalWidth, height: naturalHeight });    setInitial({ width, height });    // eslint-disable-next-line react-hooks/exhaustive-deps}, [])  
// 初始图片缩放比例(图片有原始的图片大小)const imgScaleRateX = initial.width / natural.width;const imgScaleRateY = initial.height / natural.height;

图片缩放

图片缩放可以监听onWheel事件,事件对象event有一个记录滚轮滚动的属性deltaY,当向上滚动时deltaY,向下滚动时<code>deltaY>0。每次滚动修改其缩放的比例,同时更改transform样式按比例进行缩放。

So implementieren Sie die Skalierung in React

const labelLeft = parseInt(`${imgInfo.lableLeft}`, 10) * imgScaleRateX;const labelTop = parseInt(`${imgInfo.lableTop}`, 10) * imgScaleRateY;
// 图标相对父元素坐标 = 图标位置坐标 + 图片坐标const labelLeft = parseInt(`${imgInfo.lableLeft}`, 10) * imgScaleRateX + Number(imgStyle.left || WIDTH / 2);
const labelTop = parseInt(`${imgInfo.lableTop}`, 10) * imgScaleRateY + Number(imgStyle.top || HEIGHT / 2);

如果没有设置transformOrigin,默认是相对于图片中心进行缩放,但是在初始为了让图片在可视区域内水平垂直居中,使用了transform: translate(-50%, -50%);,因此为了缩放时相对于图片中心点,需要设置matrix的第5、6个参数矫正transformOrigintransform: matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})

车站标注

首先,定义一个常量表示图标的坐标,这个坐标是相对于原始图片左上角的定位。

const labelTransformOrigin = () => {    return `${initial.width / 2 - Number(imgInfo.lableLeft) * imgScaleRateX}px ${
        initial.height / 2 - Number(imgInfo.lableTop) * imgScaleRateY
    }px`;
}

这里,解释一下原始图的概念:
So implementieren Sie die Skalierung in React

随便在网上查看一个图片元素,比如上面。1200 x 900是页面定的图片大小,但图片还有一个真实大小4535 x 3402。

要计算图标在没有平移缩放时的初始坐标之前,需要算出图片的缩放比例(不是上面的rate):

const imgInfo = {
  lableLeft: "1900",
  lableTop: "2000",
}

const WIDTH = 1200;
const HEIGHT = 900;
const SCALE = 0.2;

const DynamicStyle= () => {

  const imgRef = React.createRef<HTMLImageElement>();
  /** 初始化缩放比例,默认为1 */
  const [rate, setRate] = useState(1);
  /** 图片样式 */
  const [imgStyle, setImgStyle] = useState<React.CSSProperties>({});
  /** 记录鼠标是否按下 */
  const [mouseDowmFlag, setMouseDowmFlag] = useState(false);
  /** 记录鼠标按下的坐标 */
  const [mouseDowmPos, setMouseDowmPos] = useState<{x: number, y: number}>({x: 0, y: 0})
  /** 图片原始大小,默认设置为1是防止计算图片原始大小与初始大小比例出现无穷大 */
  const [natural, setNatural] = useState<{width: number, height: number}>({width: 1, height: 1});
  /** 图片现在大小 */
  const [initial, setInitial] = useState<{width: number, height: number}>({width: WIDTH, height: HEIGHT});

  useEffect(() => {
    const { naturalWidth, naturalHeight, width, height } = imgRef.current as HTMLImageElement;
    setNatural({ width: naturalWidth, height: naturalHeight });
    setInitial({ width, height });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    document.onmouseover = () => {
      if (mouseDowmFlag) {
        setMouseDowmFlag(false);
      }
    };
    return () => {
      document.onmouseover = null;
    };
  }, [mouseDowmFlag])

  /** 缩放 */
  const handleWheelImage = (event: React.WheelEvent<HTMLImageElement>) => {
    // 向上为负,向下为正
    const bigger = event.deltaY > 0 ? -1 : 1;
    // transform偏移量
    const transformX = -initial.width / 2;
    const transformY = -initial.height / 2;
    if (bigger > 0 && rate < 2) {
      const enlargeRate = rate + SCALE;
      setImgStyle({
        ...imgStyle,
        transform: `matrix(${enlargeRate}, 0, 0, ${enlargeRate}, ${transformX}, ${transformY})`, // 默认以图片中心为原点进行缩放
      });
      setRate(enlargeRate);
    } else if (bigger < 0 && rate > 1) {
      const shrinkRate = rate - SCALE;
      setImgStyle({
        ...imgStyle,
        transform: `matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})`,
      });
      setRate(shrinkRate);
    }
  }

  /** 平移 */
  const handleMouseDown = (event: React.MouseEvent<HTMLImageElement>) => {
    const { clientX, clientY } = event;
    event.stopPropagation();
    event.preventDefault(); // 阻止浏览器默认行为,拖动会打开图片
    setMouseDowmFlag(true); // 控制只有在鼠标按下后才会执行mousemove
    setMouseDowmPos({
      x: clientX,
      y: clientY,
    });
  };

  const handleMouseMove = (event: React.MouseEvent<HTMLImageElement>) => {
    event.stopPropagation();
    event.preventDefault();
    const { clientX, clientY } = event;
    const diffX = clientX - mouseDowmPos.x;
    const diffY = clientY - mouseDowmPos.y;
    if (!mouseDowmFlag || (diffX === 0 && diffY === 0)) return;
    const { offsetLeft, offsetTop } = imgRef.current as HTMLImageElement;
    const offsetX = parseInt(`${diffX + offsetLeft}`, 10);
    const offsetY = parseInt(`${diffY + offsetTop}`, 10);

    setMouseDowmPos({
      x: clientX,
      y: clientY,
    });
    setImgStyle({
      ...imgStyle,
      left: offsetX,
      top: offsetY,
    });
  };

  const handleMouseUp = (event: React.MouseEvent<HTMLImageElement>) => {
    event.stopPropagation();
    event.preventDefault();
    setMouseDowmFlag(false);
  };

  // 初始图片缩放比例(图片有原始的图片大小)
  const imgScaleRateX = initial.width / natural.width;
  const imgScaleRateY = initial.height / natural.height;

  const labelTransformOrigin = () => {
    return `${initial.width / 2 - Number(imgInfo.lableLeft) * imgScaleRateX}px ${
      initial.height / 2 - Number(imgInfo.lableTop) * imgScaleRateY
    }px`;
  }

  /** 图标位置计算 */
  const labelStyle = (): React.CSSProperties => {
    const transformX = -initial.width / 2;
    const transformY = -initial.height / 2;
    // 图标相对父元素坐标 = 图标初始位置坐标 + 平移量
    const labelLeft = parseInt(`${imgInfo.lableLeft}`, 10) * imgScaleRateX + Number(imgStyle.left || WIDTH / 2);
    const labelTop = parseInt(`${imgInfo.lableTop}`, 10) * imgScaleRateY + Number(imgStyle.top || HEIGHT / 2);
    return {
      left: labelLeft,
      top: labelTop,
      transformOrigin: labelTransformOrigin(),
      transform: `matrix(${rate}, 0, 0, ${rate}, ${transformX}, ${transformY})`,
    }
  }


  return (
    <div className={styles.imgArea}>
      <img 
        src={mapImg} 
        alt=&#39;part&#39; 
        height={HEIGHT} 
        style={imgStyle}
        ref={imgRef}
        onWheel={handleWheelImage}
        onMouseDown={handleMouseDown}
        onMouseMove={handleMouseMove}
        onMouseUp={handleMouseUp}
      >
      </img>
      <span className={styles.label} style={labelStyle()}></span>
    </div>
  )
}

图标初始的坐标就可以计算出:

rrreee

当图片平移时,图标也需要跟着平移,这是的坐标计算:

rrreee

So implementieren Sie die Skalierung in React

当图片缩放时,图标需要随着图片一起缩放。如果没有对图标设置transformOrigin,默认时相对图标的中心缩放的。为了保证图标随着图片一起缩放,那就必须使得图片和图标的缩放参照原点相同,图标的transformOriginUm die Anfangskoordinaten des Symbols ohne Übersetzung und Skalierung zu berechnen, müssen Sie das Skalierungsverhältnis des Bildes berechnen (nicht die Rate oben):

rrreee

Die Anfangskoordinaten des Symbols können sein berechnet: So implementieren Sie die Skalierung in Reactrrreee

Wenn das Bild übersetzt wird, muss auch das Symbol übersetzt werden. Dies ist die Koordinatenberechnung:

rrreee

So implementieren Sie die Skalierung in React

Wenn das Bild skaliert wird, muss das Symbol mit dem Bild skaliert werden. Wenn transformOrigin nicht für das Symbol festgelegt ist, wird es standardmäßig relativ zur Mitte des Symbols skaliert. Um sicherzustellen, dass das Symbol mit dem Bild skaliert, muss der Skalierungsreferenzursprung des Bildes und des Symbols gleich sein und der transformOrigin des Symbols sollte auf den Abstand relativ zum Ursprung eingestellt werden des Bildes. rrreee

🎜🎜Gesamtcodebeispiel: 🎜rrreee🎜Empfohlenes Lernen: „🎜Video-Tutorial reagieren🎜“🎜🎜

Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Skalierung in React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn