ホームページ  >  記事  >  ウェブフロントエンド  >  Reactでスケーリングを実装する方法

Reactでスケーリングを実装する方法

藏色散人
藏色散人オリジナル
2022-12-28 10:13:072267ブラウズ

React のスケーリング方法: 1. onWheel イベントをリッスンする; 2. イベント オブジェクトの属性 deltaY を設定し、上にスクロールする場合は「deltaY0」を設定します。 3. スクロールするたびに拡大縮小率を変更し、それに応じて拡大縮小するように変換スタイルを変更します。

Reactでスケーリングを実装する方法

#このチュートリアルの動作環境: Windows 10 システム、React バージョン 18.0.0、Dell G3 コンピューター。

React でスケーリングを実現するにはどうすればよいですか?

React 画像のスケーリングとパン (位置、変換の実装)

多くの Web ページでは、コピーの説明を補足するためにいくつかの画像が添付されます。たとえば、次のようになります。住所について話すときは、その隣に地図が添付され、地図上に住所がマークされます。添付された写真が小さすぎて、住所の特定の情報をはっきりと見ることが難しい場合、製品マネージャーによっては、写真のパン、ズームイン、ズームアウトの機能を設計することがあります。この記事では上記の機能を一つずつ実装していきます。

早速、最初にレンダリングをお見せします:

Reactでスケーリングを実装する方法

主な 3 つの機能ポイント:

    画像のパン
  • 画像ズーム
  • ステーション ラベル
画像パンニング

画像パンニングは、次の 3 つのイベントを監視することで実装できます:

onMouseDown、onMouseMove、 onMouseUp
onMouseDownイベントは、各マウスが押された座標位置を記録します;
onMouseMoveイベントは、各移動の距離を計算し、それが画像からの距離に追加されます。ドラッグ前の親要素の距離は、親要素を基準としたドラッグされた画像の距離に等しくなります。
onMouseUp イベントがトリガーされると、ログアウトするか、onMouseDown およびイベントの実行を禁止します。 onMouseMove イベントが実行されず、マウスの移動が防止されます。画像がパンされます。

これら 3 つのイベントはブラウザのデフォルトの動作を防ぐ必要があります。そうしないと、移動時に画像が自動的に開かれてしまいます。


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>
  )
}

Picturezoom

Picturezoom は

onWheel イベントをリッスンできます。イベント オブジェクト event には次の属性があります。ホイールのスクロールを記録します。deltaY、上にスクロールする場合は deltaY、下にスクロールする場合は deltaY>0。各スクロールはスケーリング率を変更し、同時に transform スタイルを比例的にスケーリングするように変更します。

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;
  }
}

transformOrigin が設定されていない場合、デフォルトでは画像の中心を基準にスケールしますが、最初は画像を水平方向に中央に配置します。表示領域内で垂直方向に transform:translate(-50%, -50%); を使用したため、画像の中心点を基準にしてスケールするには、5 番目と 6 番目の値を設定する必要があります。 matrix transformOrigintransform:matrix(${shrinkRate}, 0, 0, ${shrinkRate}, ${transformX}, ${transformY})# のパラメータ修正##ステーションのラベル付け

#まず、アイコンの座標を表す定数を定義します。この座標は、元の画像の左上隅を基準とします。

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

ここで、元の画像のコンセプトを説明します:


Reactでスケーリングを実装する方法インターネット上の画像要素 (上記のような画像要素) を確認してください。ページ上で指定されている画像サイズは 1200 x 900 ですが、実際のサイズは 4535 x 3402 もあります。

移動や拡大縮小を行わずにアイコンの初期座標を計算する前に、画像の拡大縮小率 (上記の

rate

ではありません) を計算する必要があります。アイコンの初期座標は次のように計算できます: <pre class="brush:php;toolbar:false;">/** 图片原始大小,默认设置为1是防止计算图片原始大小与初始大小比例出现无穷大 */const [natural, setNatural] = useState&lt;{width: number, height: number}&gt;({width: 1, height: 1});/** 图片现在大小 */const [initial, setInitial] = useState&lt;{width: number, height: number}&gt;({width: WIDTH, height: HEIGHT});useEffect(() =&gt; { 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;</pre>画像が翻訳されると、アイコンも翻訳される必要があります。これは座標計算です:

const labelLeft = parseInt(`${imgInfo.lableLeft}`, 10) * imgScaleRateX;const labelTop = parseInt(`${imgInfo.lableTop}`, 10) * imgScaleRateY;

##画像をズームすると、アイコンも画像に合わせて拡大縮小する必要があります。

transformOrigin

がアイコンに設定されていない場合、デフォルトではアイコンの中心を基準にしてスケールされます。アイコンが画像に合わせてスケーリングされるようにするには、画像とアイコンのスケーリング基準原点が同じである必要があり、アイコンの Reactでスケーリングを実装する方法transformOrigin

は、画像の原点からの相対距離に設定する必要があります。画像。

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

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

推奨学習: 「Reactでスケーリングを実装する方法react ビデオ チュートリアル

以上がReactでスケーリングを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。