Move interaction to left click and added middle click move right click pointer

This commit is contained in:
Mitchell McCaffrey 2021-09-02 09:28:45 +10:00
parent 659d3dd9e1
commit 5e407ba72d
14 changed files with 236 additions and 64 deletions

View File

@ -67,6 +67,7 @@
"socket.io-msgpack-parser": "^3.0.1", "socket.io-msgpack-parser": "^3.0.1",
"source-map-explorer": "^2.5.2", "source-map-explorer": "^2.5.2",
"theme-ui": "^0.10.0", "theme-ui": "^0.10.0",
"tiny-typed-emitter": "^2.1.0",
"use-image": "^1.0.8", "use-image": "^1.0.8",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"webrtc-adapter": "^8.1.0" "webrtc-adapter": "^8.1.0"

View File

@ -102,6 +102,9 @@ function Note({
} }
function handleClick(event: Konva.KonvaEventObject<MouseEvent>) { function handleClick(event: Konva.KonvaEventObject<MouseEvent>) {
if (event.evt.button !== 0) {
return;
}
if (draggable) { if (draggable) {
const noteNode = event.target; const noteNode = event.target;
onNoteMenuOpen && onNoteMenuOpen(note.id, noteNode, true); onNoteMenuOpen && onNoteMenuOpen(note.id, noteNode, true);
@ -111,6 +114,9 @@ function Note({
// Store note pointer down time to check for a click when note is locked // Store note pointer down time to check for a click when note is locked
const notePointerDownTimeRef = useRef<number>(0); const notePointerDownTimeRef = useRef<number>(0);
function handlePointerDown(event: Konva.KonvaEventObject<PointerEvent>) { function handlePointerDown(event: Konva.KonvaEventObject<PointerEvent>) {
if (event.evt.button !== 0) {
return;
}
if (draggable) { if (draggable) {
setPreventMapInteraction(true); setPreventMapInteraction(true);
} }
@ -120,6 +126,9 @@ function Note({
} }
function handlePointerUp(event: Konva.KonvaEventObject<PointerEvent>) { function handlePointerUp(event: Konva.KonvaEventObject<PointerEvent>) {
if (event.evt.button !== 0) {
return;
}
if (draggable) { if (draggable) {
setPreventMapInteraction(false); setPreventMapInteraction(false);
} }

View File

@ -197,7 +197,10 @@ function Token({
setAttachmentOverCharacter(false); setAttachmentOverCharacter(false);
} }
function handleClick() { function handleClick(event: Konva.KonvaEventObject<MouseEvent>) {
if (event.evt.button !== 0) {
return;
}
if (selectable && draggable && transformRootRef.current) { if (selectable && draggable && transformRootRef.current) {
onTokenMenuOpen(tokenState.id, transformRootRef.current, true); onTokenMenuOpen(tokenState.id, transformRootRef.current, true);
} }
@ -207,6 +210,9 @@ function Token({
// Store token pointer down time to check for a click when token is locked // Store token pointer down time to check for a click when token is locked
const tokenPointerDownTimeRef = useRef<number>(0); const tokenPointerDownTimeRef = useRef<number>(0);
function handlePointerDown(event: Konva.KonvaEventObject<PointerEvent>) { function handlePointerDown(event: Konva.KonvaEventObject<PointerEvent>) {
if (event.evt.button !== 0) {
return;
}
if (draggable) { if (draggable) {
setPreventMapInteraction(true); setPreventMapInteraction(true);
} }
@ -216,6 +222,9 @@ function Token({
} }
function handlePointerUp(event: Konva.KonvaEventObject<PointerEvent>) { function handlePointerUp(event: Konva.KonvaEventObject<PointerEvent>) {
if (event.evt.button !== 0) {
return;
}
if (draggable) { if (draggable) {
setPreventMapInteraction(false); setPreventMapInteraction(false);
} }

View File

@ -3,17 +3,20 @@ import { Box } from "theme-ui";
import ReactResizeDetector from "react-resize-detector"; import ReactResizeDetector from "react-resize-detector";
import { Stage, Layer, Image, Group } from "react-konva"; import { Stage, Layer, Image, Group } from "react-konva";
import Konva from "konva"; import Konva from "konva";
import { EventEmitter } from "events";
import useMapImage from "../../hooks/useMapImage"; import useMapImage from "../../hooks/useMapImage";
import usePreventOverscroll from "../../hooks/usePreventOverscroll"; import usePreventOverscroll from "../../hooks/usePreventOverscroll";
import useStageInteraction from "../../hooks/useStageInteraction"; import useStageInteraction from "../../hooks/useStageInteraction";
import useImageCenter from "../../hooks/useImageCenter"; import useImageCenter from "../../hooks/useImageCenter";
import usePreventContextMenu from "../../hooks/usePreventContextMenu";
import { getGridMaxZoom } from "../../helpers/grid"; import { getGridMaxZoom } from "../../helpers/grid";
import KonvaBridge from "../../helpers/KonvaBridge"; import KonvaBridge from "../../helpers/KonvaBridge";
import { MapInteractionProvider } from "../../contexts/MapInteractionContext"; import {
MapInteractionEmitter,
MapInteractionProvider,
} from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { GridProvider } from "../../contexts/GridContext"; import { GridProvider } from "../../contexts/GridContext";
import { useKeyboard } from "../../contexts/KeyboardContext"; import { useKeyboard } from "../../contexts/KeyboardContext";
@ -72,6 +75,7 @@ function MapInteraction({
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
usePreventOverscroll(containerRef); usePreventOverscroll(containerRef);
usePreventContextMenu(containerRef);
const [mapWidth, mapHeight] = useImageCenter( const [mapWidth, mapHeight] = useImageCenter(
map, map,
@ -85,8 +89,9 @@ function MapInteraction({
); );
const previousSelectedToolRef = useRef(selectedToolId); const previousSelectedToolRef = useRef(selectedToolId);
const [currentMouseButtons, setCurentMouseButtons] = useState(0);
const [interactionEmitter] = useState(new EventEmitter()); const [interactionEmitter] = useState(new MapInteractionEmitter());
useStageInteraction( useStageInteraction(
mapStageRef, mapStageRef,
@ -106,13 +111,17 @@ function MapInteraction({
onPinchEnd: () => { onPinchEnd: () => {
onSelectedToolChange(previousSelectedToolRef.current); onSelectedToolChange(previousSelectedToolRef.current);
}, },
onDrag: ({ first, last }) => { onDrag: (props) => {
const { first, last, buttons } = props;
if (buttons !== currentMouseButtons) {
setCurentMouseButtons(buttons);
}
if (first) { if (first) {
interactionEmitter.emit("dragStart"); interactionEmitter.emit("dragStart", props);
} else if (last) { } else if (last) {
interactionEmitter.emit("dragEnd"); interactionEmitter.emit("dragEnd", props);
} else { } else {
interactionEmitter.emit("drag"); interactionEmitter.emit("drag", props);
} }
}, },
} }
@ -143,6 +152,11 @@ function MapInteraction({
useKeyboard(handleKeyDown, handleKeyUp); useKeyboard(handleKeyDown, handleKeyUp);
function getCursorForTool(tool: MapToolId) { function getCursorForTool(tool: MapToolId) {
if (currentMouseButtons === 2) {
return "crosshair";
} else if (currentMouseButtons > 2) {
return "move";
}
switch (tool) { switch (tool) {
case "move": case "move":
return "move"; return "move";

View File

@ -7,6 +7,8 @@ import {
useMapWidth, useMapWidth,
useMapHeight, useMapHeight,
useInteractionEmitter, useInteractionEmitter,
leftMouseButton,
MapDragEvent,
} from "../../contexts/MapInteractionContext"; } from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { import {
@ -103,7 +105,10 @@ function DrawingTool({
}); });
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
return; return;
@ -135,7 +140,10 @@ function DrawingTool({
setIsBrushDown(true); setIsBrushDown(true);
} }
function handleBrushMove() { function handleBrushMove(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
return; return;
@ -186,7 +194,10 @@ function DrawingTool({
} }
} }
function handleBrushUp() { function handleBrushUp(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (isBrush && drawing && drawing.type === "path") { if (isBrush && drawing && drawing.type === "path") {
if (drawing.data.points.length > 1) { if (drawing.data.points.length > 1) {
onShapeAdd(drawing); onShapeAdd(drawing);

View File

@ -3,6 +3,7 @@ import shortid from "shortid";
import { Group, Line } from "react-konva"; import { Group, Line } from "react-konva";
import useImage from "use-image"; import useImage from "use-image";
import Color from "color"; import Color from "color";
import Konva from "konva";
import diagonalPattern from "../../images/DiagonalPattern.png"; import diagonalPattern from "../../images/DiagonalPattern.png";
@ -11,6 +12,8 @@ import {
useMapWidth, useMapWidth,
useMapHeight, useMapHeight,
useInteractionEmitter, useInteractionEmitter,
MapDragEvent,
leftMouseButton,
} from "../../contexts/MapInteractionContext"; } from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { import {
@ -160,7 +163,10 @@ function FogTool({
}); });
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (toolSettings.type === "brush") { if (toolSettings.type === "brush") {
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
@ -203,7 +209,10 @@ function FogTool({
setIsBrushDown(true); setIsBrushDown(true);
} }
function handleBrushMove() { function handleBrushMove(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (toolSettings.type === "brush" && isBrushDown && drawingShape) { if (toolSettings.type === "brush" && isBrushDown && drawingShape) {
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
@ -258,7 +267,10 @@ function FogTool({
} }
} }
function handleBrushUp() { function handleBrushUp(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if ( if (
(toolSettings.type === "brush" || toolSettings.type === "rectangle") && (toolSettings.type === "brush" || toolSettings.type === "rectangle") &&
drawingShape drawingShape
@ -318,7 +330,13 @@ function FogTool({
setIsBrushDown(false); setIsBrushDown(false);
} }
function handlePointerClick() { function handlePointerClick(
event: Konva.KonvaEventObject<MouseEvent | TouchEvent>
) {
// Left click only
if (event.evt instanceof MouseEvent && event.evt.button !== 0) {
return;
}
if (toolSettings.type === "polygon") { if (toolSettings.type === "polygon") {
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (brushPosition) { if (brushPosition) {

View File

@ -1,7 +1,11 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Group } from "react-konva"; import { Group } from "react-konva";
import { useInteractionEmitter } from "../../contexts/MapInteractionContext"; import {
useInteractionEmitter,
MapDragEvent,
leftMouseButton,
} from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { import {
useGrid, useGrid,
@ -40,8 +44,9 @@ function MeasureTool({ map, active }: MapMeasureProps) {
const gridOffset = useGridOffset(); const gridOffset = useGridOffset();
const mapStageRef = useMapStage(); const mapStageRef = useMapStage();
const [drawingShapeData, setDrawingShapeData] = const [drawingShapeData, setDrawingShapeData] = useState<MeasureData | null>(
useState<MeasureData | null>(null); null
);
const [isBrushDown, setIsBrushDown] = useState(false); const [isBrushDown, setIsBrushDown] = useState(false);
const gridScale = parseGridScale(active ? grid.measurement.scale : null); const gridScale = parseGridScale(active ? grid.measurement.scale : null);
@ -75,7 +80,10 @@ function MeasureTool({ map, active }: MapMeasureProps) {
}); });
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
return; return;
@ -89,7 +97,10 @@ function MeasureTool({ map, active }: MapMeasureProps) {
setIsBrushDown(true); setIsBrushDown(true);
} }
function handleBrushMove() { function handleBrushMove(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (isBrushDown && drawingShapeData && brushPosition && mapImage) { if (isBrushDown && drawingShapeData && brushPosition && mapImage) {
const { points } = getUpdatedShapeData( const { points } = getUpdatedShapeData(
@ -123,7 +134,10 @@ function MeasureTool({ map, active }: MapMeasureProps) {
} }
} }
function handleBrushUp() { function handleBrushUp(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
setDrawingShapeData(null); setDrawingShapeData(null);
setIsBrushDown(false); setIsBrushDown(false);
} }

View File

@ -3,7 +3,11 @@ import shortid from "shortid";
import { Group } from "react-konva"; import { Group } from "react-konva";
import Konva from "konva"; import Konva from "konva";
import { useInteractionEmitter } from "../../contexts/MapInteractionContext"; import {
useInteractionEmitter,
MapDragEvent,
leftMouseButton,
} from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { useUserId } from "../../contexts/UserIdContext"; import { useUserId } from "../../contexts/UserIdContext";
@ -72,7 +76,10 @@ function NoteTool({
}); });
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition || !userId) { if (!brushPosition || !userId) {
return; return;
@ -94,7 +101,10 @@ function NoteTool({
setIsBrushDown(true); setIsBrushDown(true);
} }
function handleBrushMove() { function handleBrushMove(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (noteData) { if (noteData) {
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition) { if (!brushPosition) {
@ -114,7 +124,10 @@ function NoteTool({
} }
} }
function handleBrushUp() { function handleBrushUp(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (noteData && creatingNoteRef.current) { if (noteData && creatingNoteRef.current) {
onNoteCreate([noteData]); onNoteCreate([noteData]);
onNoteMenuOpen(noteData.id, creatingNoteRef.current, true); onNoteMenuOpen(noteData.id, creatingNoteRef.current, true);

View File

@ -1,10 +1,13 @@
import { useEffect } from "react"; import { useEffect, useRef } from "react";
import { Group } from "react-konva"; import { Group } from "react-konva";
import { import {
useMapWidth, useMapWidth,
useMapHeight, useMapHeight,
useInteractionEmitter, useInteractionEmitter,
MapDragEvent,
leftMouseButton,
rightMouseButton,
} from "../../contexts/MapInteractionContext"; } from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
import { useGridStrokeWidth } from "../../contexts/GridContext"; import { useGridStrokeWidth } from "../../contexts/GridContext";
@ -41,11 +44,9 @@ function PointerTool({
const gridStrokeWidth = useGridStrokeWidth(); const gridStrokeWidth = useGridStrokeWidth();
const mapStageRef = useMapStage(); const mapStageRef = useMapStage();
useEffect(() => { const brushDownRef = useRef(false);
if (!active) {
return;
}
useEffect(() => {
const mapStage = mapStageRef.current; const mapStage = mapStageRef.current;
function getBrushPosition() { function getBrushPosition() {
@ -56,19 +57,27 @@ function PointerTool({
return getRelativePointerPositionNormalized(mapImage); return getRelativePointerPositionNormalized(mapImage);
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
const brushPosition = getBrushPosition(); if ((leftMouseButton(props) && active) || rightMouseButton(props)) {
brushPosition && onPointerDown?.(brushPosition); const brushPosition = getBrushPosition();
brushPosition && onPointerDown?.(brushPosition);
brushDownRef.current = true;
}
} }
function handleBrushMove() { function handleBrushMove() {
const brushPosition = getBrushPosition(); if (brushDownRef.current) {
brushPosition && visible && onPointerMove?.(brushPosition); const brushPosition = getBrushPosition();
brushPosition && visible && onPointerMove?.(brushPosition);
}
} }
function handleBrushUp() { function handleBrushUp() {
const brushPosition = getBrushPosition(); if (brushDownRef.current) {
brushPosition && onPointerUp?.(brushPosition); const brushPosition = getBrushPosition();
brushPosition && onPointerUp?.(brushPosition);
brushDownRef.current = false;
}
} }
interactionEmitter?.on("dragStart", handleBrushDown); interactionEmitter?.on("dragStart", handleBrushDown);

View File

@ -7,6 +7,8 @@ import {
useMapWidth, useMapWidth,
useMapHeight, useMapHeight,
useInteractionEmitter, useInteractionEmitter,
MapDragEvent,
leftMouseButton,
} from "../../contexts/MapInteractionContext"; } from "../../contexts/MapInteractionContext";
import { useMapStage } from "../../contexts/MapStageContext"; import { useMapStage } from "../../contexts/MapStageContext";
@ -96,7 +98,10 @@ function SelectTool({
}); });
} }
function handleBrushDown() { function handleBrushDown(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition || preventSelectionRef.current) { if (!brushPosition || preventSelectionRef.current) {
return; return;
@ -121,7 +126,10 @@ function SelectTool({
setIsBrushDown(true); setIsBrushDown(true);
} }
function handleBrushMove() { function handleBrushMove(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
const brushPosition = getBrushPosition(); const brushPosition = getBrushPosition();
if (!brushPosition || preventSelectionRef.current) { if (!brushPosition || preventSelectionRef.current) {
return; return;
@ -172,7 +180,10 @@ function SelectTool({
} }
} }
function handleBrushUp() { function handleBrushUp(props: MapDragEvent) {
if (!leftMouseButton(props)) {
return;
}
if (preventSelectionRef.current) { if (preventSelectionRef.current) {
return; return;
} }

View File

@ -1,6 +1,21 @@
import React, { useContext } from "react"; import React, { useContext } from "react";
import { EventEmitter } from "stream"; import { FullGestureState } from "react-use-gesture/dist/types";
import useDebounce from "../hooks/useDebounce"; import useDebounce from "../hooks/useDebounce";
import { TypedEmitter } from "tiny-typed-emitter";
export type MapDragEvent = Omit<FullGestureState<"drag">, "event"> & {
event: React.PointerEvent<Element> | PointerEvent;
};
export type MapDragEventHandler = (props: MapDragEvent) => void;
export interface MapInteractionEvents {
dragStart: MapDragEventHandler;
drag: MapDragEventHandler;
dragEnd: MapDragEventHandler;
}
export class MapInteractionEmitter extends TypedEmitter<MapInteractionEvents> {}
type MapInteraction = { type MapInteraction = {
stageScale: number; stageScale: number;
@ -9,29 +24,33 @@ type MapInteraction = {
setPreventMapInteraction: React.Dispatch<React.SetStateAction<boolean>>; setPreventMapInteraction: React.Dispatch<React.SetStateAction<boolean>>;
mapWidth: number; mapWidth: number;
mapHeight: number; mapHeight: number;
interactionEmitter: EventEmitter | null; interactionEmitter: MapInteractionEmitter | null;
}; };
export const StageScaleContext = export const StageScaleContext = React.createContext<
React.createContext<MapInteraction["stageScale"] | undefined>(undefined); MapInteraction["stageScale"] | undefined
export const DebouncedStageScaleContext = >(undefined);
React.createContext<MapInteraction["stageScale"] | undefined>(undefined); export const DebouncedStageScaleContext = React.createContext<
export const StageWidthContext = MapInteraction["stageScale"] | undefined
React.createContext<MapInteraction["stageWidth"] | undefined>(undefined); >(undefined);
export const StageHeightContext = export const StageWidthContext = React.createContext<
React.createContext<MapInteraction["stageHeight"] | undefined>(undefined); MapInteraction["stageWidth"] | undefined
export const SetPreventMapInteractionContext = >(undefined);
React.createContext<MapInteraction["setPreventMapInteraction"] | undefined>( export const StageHeightContext = React.createContext<
undefined MapInteraction["stageHeight"] | undefined
); >(undefined);
export const MapWidthContext = export const SetPreventMapInteractionContext = React.createContext<
React.createContext<MapInteraction["mapWidth"] | undefined>(undefined); MapInteraction["setPreventMapInteraction"] | undefined
export const MapHeightContext = >(undefined);
React.createContext<MapInteraction["mapHeight"] | undefined>(undefined); export const MapWidthContext = React.createContext<
export const InteractionEmitterContext = MapInteraction["mapWidth"] | undefined
React.createContext<MapInteraction["interactionEmitter"] | undefined>( >(undefined);
undefined export const MapHeightContext = React.createContext<
); MapInteraction["mapHeight"] | undefined
>(undefined);
export const InteractionEmitterContext = React.createContext<
MapInteraction["interactionEmitter"] | undefined
>(undefined);
export function MapInteractionProvider({ export function MapInteractionProvider({
value, value,
@ -152,3 +171,15 @@ export function useDebouncedStageScale() {
} }
return context; return context;
} }
export function leftMouseButton(event: MapDragEvent) {
return event.buttons <= 1;
}
export function middleMouseButton(event: MapDragEvent) {
return event.buttons === 4;
}
export function rightMouseButton(event: MapDragEvent) {
return event.buttons === 2;
}

View File

@ -0,0 +1,25 @@
import React, { useEffect } from "react";
function usePreventContextMenu(elementRef: React.RefObject<HTMLElement>) {
useEffect(() => {
// Stop conext menu i.e. right click dialog
function preventContextMenu(event: MouseEvent) {
event.preventDefault();
return false;
}
const element = elementRef.current;
if (element) {
element.addEventListener("contextmenu", preventContextMenu, {
passive: false,
});
}
return () => {
if (element) {
element.removeEventListener("contextmenu", preventContextMenu);
}
};
}, [elementRef]);
}
export default usePreventContextMenu;

View File

@ -67,6 +67,7 @@ function useStageInteraction(
return; return;
} }
const { event, last } = props; const { event, last } = props;
// Prevent double zoom on wheel end
if (!last) { if (!last) {
const { pixelY } = normalizeWheel(event); const { pixelY } = normalizeWheel(event);
@ -178,7 +179,7 @@ function useStageInteraction(
gesture.onDragStart && gesture.onDragStart(props); gesture.onDragStart && gesture.onDragStart(props);
}, },
onDrag: (props) => { onDrag: (props) => {
const { delta, pinching } = props; const { delta, pinching, buttons } = props;
const stage = stageRef.current; const stage = stageRef.current;
if ( if (
preventInteraction || preventInteraction ||
@ -191,7 +192,8 @@ function useStageInteraction(
const [dx, dy] = delta; const [dx, dy] = delta;
const stageTranslate = stageTranslateRef.current; const stageTranslate = stageTranslateRef.current;
if (tool === "move") { // Move with move tool and left click or any mouse button but right click
if ((tool === "move" && buttons < 2) || buttons > 2) {
const newTranslate = { const newTranslate = {
x: stageTranslate.x + dx, x: stageTranslate.x + dx,
y: stageTranslate.y + dy, y: stageTranslate.y + dy,

View File

@ -13181,6 +13181,11 @@ tiny-invariant@^1.0.2:
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
tiny-typed-emitter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5"
integrity sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==
tiny-warning@^1.0.0, tiny-warning@^1.0.3: tiny-warning@^1.0.0, tiny-warning@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"