React TypeScript:鼠标移动时重新渲染div

问题描述 投票:0回答:2

[我正在尝试制作一个图像放大器,当我单击图像时,将鼠标移到图像上方时,我将zoomOn从true切换为false,我将x,y位置保存为状态,我正在渲染放大镜并使用x和y定位背景图像。但是由于某种原因,当我移动光标时,顶部,左侧的值没有更新?

import React, { useState } from 'react';

const Magnify: React.FC = () => {

  const [state, setState] = useState({
    mouseOver: false,
    zoomId: '',
    zoomOn: false,
    zoomPositionX: 0,
    zoomPositionY: 0,
  });

  const {
    zoomId,
    zoomOn,
    mouseOver,
    zoomPositionX,
    zoomPositionY,
  } = state;


  const toggleZoom = () => {
    setState((prev) => ({
      ...prev,
      zoomOn: !zoomOn,
    }));
  };

  const mouseEnter = () => {
    setState((prev) => ({
      ...prev,
      mouseOver: true,
    }));
  };

  const mouseLeave = () => {
    setState((prev) => ({
      ...prev,
      mouseOver: false,
    }));
  };

  const mouseMove = (event: React.MouseEvent) => {
    event.persist();
    if (zoomOn) {
      setState((prev) => ({
        ...prev,
        zoomPositionX: event.nativeEvent.offsetX,
        zoomPositionY: event.nativeEvent.offsetY,
      }));
      renderMagnifier(); // <---- This isnt right!??
    }
  };
  const renderMagnifier = () => {
    return <div className='bus--magnifier' style={magnifierStyle()}></div>;
  };
  const magnifierStyle = () => {
    return {
      backgroundImage: `url('bigtestImage.jpg')`,
      backgroundPosition: `${zoomPositionX}px ${zoomPositionY}px`,
      backgroundRepeat: 'no-repeat',
      backgroundSize: '1000px 1000px',
      left: `${zoomPositionY}`,
      top: `${zoomPositionX}`,
    };
  };

  return (
    <div className='magnify'>
      <img
        src='bigtestImage.jpg'
        width={720}
        height={720}
        onClick={toggleZoom}
        onMouseEnter={mouseEnter}
        onMouseLeave={mouseLeave}
        onMouseMove={mouseMove}
        className={
          zoomOn && mouseOver
            ? 'magnify--image magnify--over-on'
            : 'magnify--image magnify--over-off'
        }
      />
      {renderMagnifier()}
    </div>
  );
};

export { Magnify };

和scss

.magnify {
    max-width: $page-max-width;
    margin: 12px auto;
    position: relative;
    &--image {
        border-radius: 5px;
        box-shadow: $depth-1;
        cursor: zoom-in;
    }
    &--over-on {
        cursor: none;
    }
    &--over-off {
        cursor: zoom-in;
    }
    &--magnifier {
        position: absolute;
        border: 2px solid white;
        border-radius: 5px;
        cursor: none;
        width: 250px;
        height: 250px;
        pointer-events: none;  
      }
}
reactjs typescript
2个回答
1
投票

renderMagnifier只是一个功能组件,因此将其用作React.Component并将zoomPositionX和zoomPositionY传递给它们。 Magnify中的更改状态更改将导致Magnify及其子组件的重新呈现。

获取更改

const Magnifier: React.FC = ({ zoomPositionX, zoomPositionY }) => {

  const magnifierStyle =  {
      backgroundImage: `url('bigtestImage.jpg')`,
      backgroundPosition: `${zoomPositionX}px ${zoomPositionY}px`,
      backgroundRepeat: 'no-repeat',
      backgroundSize: '1000px 1000px',
      left: `${zoomPositionY}`,
      top: `${zoomPositionX}`,
  };

  return <div className="bus--magnifier" style={magnifierStyle}></div>;
}

const Magnify: React.FC = () => {

  const [state, setState] = useState({
    mouseOver: false,
    zoomId: '',
    zoomOn: false,
    zoomPositionX: 0,
    zoomPositionY: 0,
  });

  const {
    zoomId,
    zoomOn,
    mouseOver,
    zoomPositionX,
    zoomPositionY,
  } = state;


  const toggleZoom = () => {
    setState((prev) => ({
      ...prev,
      zoomOn: !zoomOn,
    }));
  };

  const mouseEnter = () => {
    setState((prev) => ({
      ...prev,
      mouseOver: true,
    }));
  };

  const mouseLeave = () => {
    setState((prev) => ({
      ...prev,
      mouseOver: false,
    }));
  };

  const mouseMove = (event: React.MouseEvent) => {
    event.persist();
    if (zoomOn) {
      setState((prev) => ({
        ...prev,
        zoomPositionX: event.nativeEvent.offsetX,
        zoomPositionY: event.nativeEvent.offsetY,
      }));
      renderMagnifier(); // <---- This isnt right!??
    }
  };

  return (
    <div className='magnify'>
      <img
        src='bigtestImage.jpg'
        width={720}
        height={720}
        onClick={toggleZoom}
        onMouseEnter={mouseEnter}
        onMouseLeave={mouseLeave}
        onMouseMove={mouseMove}
        className={
          zoomOn && mouseOver
            ? 'magnify--image magnify--over-on'
            : 'magnify--image magnify--over-off'
        }
      />
      <Magnifier zoomPositionX={zoomPositionX} zoomPositionY={zoomPositionY} />
    </div>
  );
}

0
投票

状态更改后,尝试使用React Hooks的useMemo更新您的放大镜样式。

    import { useMemo } from 'react';
    ...
    const magnifierStyle = useMemo(() => {
         return {
          backgroundImage: `url('bigtestImage.jpg')`,
          backgroundPosition: `${state.zoomPositionX}px ${state.zoomPositionY}px`,
          backgroundRepeat: 'no-repeat',
          backgroundSize: '1000px 1000px',
          left: `${state.zoomPositionY}`,
          top: `${state.zoomPositionX}`,
         };
    }, [[state.zoomPositionX, state.zoomPositionY]]);
    ...
    const renderMagnifier = () => {
       return <div className='bus--magnifier' style={magnifierStyle}></div>;
    };
© www.soinside.com 2019 - 2024. All rights reserved.