react-spring#config TypeScript Examples

The following examples show how to use react-spring#config. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DragControls.tsx    From spacesvr with MIT License 5 votes vote down vote up
/**
 * DragControls allows for a click-and-drag control
 * of the camera
 *
 * @param props
 * @constructor
 */
export function DragControls() {
  const originEuler = useRef<Euler>(new Euler(0, 0, 0, "YXZ"));
  const setEuler = useRef<Euler>(new Euler(0, 0, 0, "YXZ"));
  const mouseDownPos = useRef<Vector2>(new Vector2(0, 0));
  const dragging = useRef(false);
  const camera = useThree((state) => state.camera);
  const { containerRef } = useEnvironment();
  const [xyz, setXYZ] = useState([0, 0, 0]);

  const { x, y, z } = useSpring({
    x: xyz[0],
    y: xyz[1],
    z: xyz[2],
    config: { ...config.default, precision: 0.0001 },
  });

  useFrame(() => {
    if (setEuler.current) {
      setEuler.current.set(x.get(), y.get(), z.get());
      camera.quaternion.setFromEuler(setEuler.current);
    }
  });

  const getNewEuler = (
    dragX: number,
    dragY: number,
    isHover?: boolean
  ): Euler => {
    const newEuler = originEuler.current.clone();
    const moveX = dragX - mouseDownPos.current.x;
    const moveY = dragY - mouseDownPos.current.y;

    const SENSITIVITY = isHover ? HOVER_SENSITIVITY : DRAG_SENSITIVITY;

    newEuler.setFromQuaternion(camera.quaternion);
    newEuler.y = originEuler.current.y - (moveX * SENSITIVITY.x) / 100;
    newEuler.x = originEuler.current.x - (moveY * SENSITIVITY.y) / 100;
    // newEuler.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, newEuler.x));

    return newEuler;
  };

  // touch move scripts
  const onMouseDown = (ev: MouseEvent) => {
    dragging.current = true;
    mouseDownPos.current.set(ev.clientX, ev.clientY);
    containerRef?.current?.classList.add("grabbing");
  };
  const onMouseMove = (ev: MouseEvent) => {
    const newEuler = getNewEuler(ev.clientX, ev.clientY, !dragging.current);
    setXYZ(newEuler.toArray());
  };
  const onMouseUp = (ev: MouseEvent) => {
    dragging.current = false;
    originEuler.current = getNewEuler(ev.clientX, ev.clientY);
    mouseDownPos.current.set(ev.clientX, ev.clientY);
    containerRef?.current?.classList.remove("grabbing");
  };

  useEffect(() => {
    document.addEventListener("mousedown", onMouseDown);
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("mouseup", onMouseUp);

    return () => {
      document.removeEventListener("mousedown", onMouseDown);
      document.removeEventListener("mousemove", onMouseMove);
      document.removeEventListener("mouseup", onMouseUp);
    };
  }, [containerRef]);

  return null;
}
Example #2
Source File: GyroControls.tsx    From spacesvr with MIT License 4 votes vote down vote up
GyroControls = (props: GyroControlsProps) => {
  const { fallback } = props;

  const camera = useThree((state) => state.camera);

  const [controls, setControls] = useState<DeviceOrientationControls>();
  const [enableGyro, setEnableGyro] = useState(false);
  const [alphaVal, setAlphaVal] = useState(0);

  // dragging for y axis offset
  const touchStartPos = useRef<Touch>(DefaultTouch);
  const currentOffset = useRef(0);
  const { alpha } = useSpring({
    alpha: alphaVal,
    config: { ...config.default, precision: 0.001 },
  });

  // try to prompt user for device controls
  useEffect(() => {
    if (!controls) {
      const func = () => {
        const cont = new DeviceOrientationControls(camera);
        cont.enabled = false; // set to disabled in case they're not working yet
        setControls(cont);
      };
      window.addEventListener("click", func);

      return () => {
        window.removeEventListener("click", func);
      };
    }
  }, [controls]);

  useFrame(() => {
    if (controls && !enableGyro) {
      // check if an event has been received yet
      if (Object.keys(controls.deviceOrientation).length !== 0) {
        setEnableGyro(true);
        controls.enabled = true;
      }
    }

    if (controls) {
      controls.alphaOffset = -alpha.get() * ALPHA_SENSITIVITY;
      controls.update();
    }
  });

  // touch move scripts
  const onTouchStart = (ev: TouchEvent) => {
    if (touchStartPos.current.id !== -1) {
      return;
    }

    if (tappedNipple(ev)) {
      touchStartPos.current = DefaultTouch;
      return;
    }

    // get last in list (most recent touch) to not confuse with movement
    const touchIndex = ev.touches.length - 1;
    const { clientX, clientY, identifier: id } = ev.touches[touchIndex];

    touchStartPos.current = { pos: new Vector2(clientX, clientY), id };
  };

  const onTouchMove = (ev: TouchEvent) => {
    const touch = getCurrentTouch(touchStartPos.current.id, ev.touches);

    if (!touch) {
      return;
    }

    const extraOffset = touch.clientX - touchStartPos.current.pos.x;
    setAlphaVal(currentOffset.current + extraOffset);
  };
  const onTouchEnd = (ev: TouchEvent) => {
    const touch = getCurrentTouch(touchStartPos.current.id, ev.changedTouches);

    if (!touch) {
      return;
    }

    const finalOffset = touch.clientX - touchStartPos.current.pos.x;
    setAlphaVal(currentOffset.current + finalOffset);
    currentOffset.current += finalOffset;
    touchStartPos.current.id = -1;
  };

  // register touch events
  useEffect(() => {
    document.addEventListener("touchstart", onTouchStart);
    document.addEventListener("touchmove", onTouchMove);
    document.addEventListener("touchend", onTouchEnd);

    return () => {
      document.removeEventListener("touchstart", onTouchStart);
      document.removeEventListener("touchmove", onTouchMove);
      document.removeEventListener("touchend", onTouchEnd);
    };
  }, []);

  if (!enableGyro) {
    return <>{fallback}</>;
  }

  return null;
}