React: Two-Finger Panning Jumps to a Different Position After Pinch-Zoom in SVG

143 Views Asked by At

I have a React component that is supposed to handle pinch-zoom and two-finger panning on an SVG element. The pinch-zoom works as expected, but I've run into an issue with two-finger panning.

"use client";

import React, { useEffect, useRef, useMemo, useState } from "react";
import { useSpring, animated } from "@react-spring/web";
import {
  createUseGesture,
  dragAction,
  pinchAction,
  wheelAction,
} from "@use-gesture/react";
import { usePathname, useRouter } from "next/navigation";
import { useMotionValue } from "framer-motion";
import { set } from "zod";

const useGesture = createUseGesture([dragAction, pinchAction, wheelAction]);

export default function Gestures({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLDivElement>(null);
  const innerRef = useRef<HTMLDivElement>(null);
  const [isPinching, setIsPinching] = useState(false);
  const [isOnWheelFired, setIsOnWheelFired] = useState(false);

  const [style, api] = useSpring(() => ({
    x: 0,
    y: 0,
    scale: 1,
    rotateZ: 0,
  }));

  useGesture(
    {
      onDrag: ({ pinching, cancel, offset: [x, y] }) => {
        if (pinching) return cancel();
        api.start({ x, y });
      },
      onWheel: ({ direction: [dx, dy], offset: [x, y], first }) => {
       
        console.log("ON WHEEL");
        if (!isOnWheelFired) {
          setIsOnWheelFired(true);
          return;
        }
        api.start({ ...style, x: -x, y: -y });
        // }
      },
      onWheelEnd: () => {
        console.log("ON WHEEL END");
        setIsOnWheelFired(false);
      },
      onPinchEnd: () => {
        api.stop();
      },
      onPinch: ({
        event,
        memo,
        origin: [pinchOriginX, pinchOriginY],
        offset: [d],
      }) => {
        // event.preventDefault();
        setIsPinching(true);
   

        api.start({
          x: style.x.get(),
          y: style.y.get(),
          scale: newScale,
        });
        return memo;
      },
    },
    {
      target: ref,
      eventOptions: { passive: false },
    }
  );

  return (
    <div>
      <div
        ref={ref}
        style={{
          touchAction: "none",
          position: "fixed",
          width: "100vw",
          height: "100vh",
        }}
      >
        <animated.div
          ref={innerRef}
          style={{
            ...style,
            touchAction: "none",
            userSelect: "none",
            MozUserSelect: "none",
            // WebkitUserDrag: "none",
            position: "absolute",
            width: "100%",
            height: "100%",
          }}
        >
          {children}
        </animated.div>
      </div>
      <div>
        test x: {style.x.get()} y: {style.y.get()} scale: {style.scale.get()}
      </div>
    </div>
  );
}

Any ideas on how to fix this?

0

There are 0 best solutions below