123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import React from "react";
- import { atom, useRecoilState } from "recoil";
- export const PanZoomRotateState = atom({
- key: "PanZoomRotate",
- default: {
- translateX: 0,
- translateY: 0,
- scale: 1,
- rotate: 0,
- },
- });
- const PanZoomRotate = ({ children }) => {
- const [dim, setDim] = useRecoilState(PanZoomRotateState);
- const wrapperRef = React.useRef(null);
- const wrappedRef = React.useRef(null);
- const stateRef = React.useRef({
- moving: false,
- });
- const onWheel = (e) => {
- if (e.altKey) {
- return;
- }
- const scaleMult = (e.deltaY * dim.scale) / 20;
- setDim((prevDim) => {
- let newScale = prevDim.scale - scaleMult;
- if (newScale > 8) {
- newScale = 8;
- }
- if (newScale < 0.3) {
- newScale = 0.3;
- }
- const { top, left } = wrappedRef.current.getBoundingClientRect();
- const displayX = e.clientX - left;
- const deltaX = displayX - (displayX / dim.scale) * newScale;
- const displayY = e.clientY - top;
- const deltaY = displayY - (displayY / dim.scale) * newScale;
- return {
- ...prevDim,
- scale: newScale,
- translateX: prevDim.translateX + deltaX,
- translateY: prevDim.translateY + deltaY,
- };
- });
- };
- const onMouseDown = (e) => {
- if (e.button === 1 || e.altKey) {
- stateRef.current.moving = true;
- stateRef.current.startX = e.clientX;
- stateRef.current.startY = e.clientY;
- stateRef.current.startTranslateX = dim.translateX;
- stateRef.current.startTranslateY = dim.translateY;
- wrapperRef.current.style.cursor = "move";
- }
- };
- const onMouseMouve = (e) => {
- if (stateRef.current.moving) {
- const [deltaX, deltaY] = [
- e.clientX - stateRef.current.startX,
- e.clientY - stateRef.current.startY,
- ];
- setDim((prevDim) => ({
- ...prevDim,
- translateX: stateRef.current.startTranslateX + deltaX,
- translateY: stateRef.current.startTranslateY + deltaY,
- }));
- }
- };
- const onMouseUp = (e) => {
- if (e.button === 1 || e.altKey) {
- stateRef.current.moving = false;
- wrapperRef.current.style.cursor = "auto";
- }
- };
- const style = {
- transform: `translate(${dim.translateX}px, ${dim.translateY}px) scale(${dim.scale}) rotate(${dim.rotate}deg)`,
- transformOrigin: "top left",
- };
- return (
- <div
- onWheel={onWheel}
- onMouseDown={onMouseDown}
- onMouseMove={onMouseMouve}
- onMouseUp={onMouseUp}
- ref={wrapperRef}
- style={{}}
- >
- <div style={{ ...style, display: "inline-block" }} ref={wrappedRef}>
- {children}
- </div>
- </div>
- );
- };
- export default PanZoomRotate;
|