mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 07:22:23 -04:00
better pan zoom with space for drag, shift for horizontal scroll and ctrl for zoom (#3080)
* more better pan zoom with space for drag, shift for horizontal scroll and ctrl for zoom * use middle mouse button for drag * improve panning with space + mousemove, remove middle mouse implementation * handle tool change after mouseup event
This commit is contained in:
parent
58b2475f42
commit
f413274fba
2 changed files with 110 additions and 60 deletions
|
@ -5,7 +5,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<script lang="ts">
|
||||
import { directionKey } from "@tslib/context-keys";
|
||||
import * as tr from "@tslib/ftl";
|
||||
import { isApplePlatform } from "@tslib/platform";
|
||||
import { getPlatformString } from "@tslib/shortcuts";
|
||||
import DropdownItem from "components/DropdownItem.svelte";
|
||||
import IconButton from "components/IconButton.svelte";
|
||||
|
@ -32,7 +31,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { drawCursor } from "./tools/tool-cursor";
|
||||
import { removeUnfinishedPolygon } from "./tools/tool-polygon";
|
||||
import { undoRedoTools, undoStack } from "./tools/tool-undo-redo";
|
||||
import { disableZoom, enableZoom, onWheelDrag } from "./tools/tool-zoom";
|
||||
import {
|
||||
disablePan,
|
||||
disableZoom,
|
||||
enablePan,
|
||||
enableZoom,
|
||||
onWheelDrag,
|
||||
onWheelDragX,
|
||||
} from "./tools/tool-zoom";
|
||||
|
||||
export let canvas;
|
||||
export let iconSize;
|
||||
|
@ -51,56 +57,70 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
});
|
||||
|
||||
// handle zoom event when mouse scroll and ctrl key are hold for panzoom
|
||||
let clicked = false;
|
||||
let dbclicked = false;
|
||||
let spaceClicked = false;
|
||||
let controlClicked = false;
|
||||
let shiftClicked = false;
|
||||
let move = false;
|
||||
let wheel = false;
|
||||
const controlKey = isApplePlatform() ? "Shift" : "Control";
|
||||
const spaceKey = " ";
|
||||
const controlKey = "Control";
|
||||
const shiftKey = "Shift";
|
||||
|
||||
onMount(() => {
|
||||
window.addEventListener("mousedown", (event) => {
|
||||
if (event.ctrlKey) {
|
||||
clicked = true;
|
||||
window.addEventListener("mousedown", () => {
|
||||
window.addEventListener("keydown", (ev) => {
|
||||
if (ev.key === spaceKey) {
|
||||
spaceClicked = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
window.addEventListener("mousemove", () => {
|
||||
if (spaceClicked || move) {
|
||||
disableFunctions();
|
||||
enablePan(canvas);
|
||||
}
|
||||
});
|
||||
window.addEventListener("mouseup", (event) => {
|
||||
if (event.ctrlKey) {
|
||||
clicked = false;
|
||||
window.addEventListener("mouseup", () => {
|
||||
if (spaceClicked) {
|
||||
spaceClicked = false;
|
||||
}
|
||||
if (move) {
|
||||
move = false;
|
||||
}
|
||||
disableFunctions();
|
||||
handleToolChanges(activeTool);
|
||||
});
|
||||
window.addEventListener("keyup", (event) => {
|
||||
if (
|
||||
event.key === spaceKey ||
|
||||
event.key === controlKey ||
|
||||
event.key === shiftKey
|
||||
) {
|
||||
spaceClicked = false;
|
||||
controlClicked = false;
|
||||
shiftClicked = false;
|
||||
move = false;
|
||||
|
||||
disableFunctions();
|
||||
handleToolChanges(activeTool);
|
||||
}
|
||||
});
|
||||
window.addEventListener("mousemove", (event) => {
|
||||
if (event.ctrlKey) {
|
||||
move = true;
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (event.key === spaceKey) {
|
||||
spaceClicked = true;
|
||||
}
|
||||
if (event.key === controlKey) {
|
||||
controlClicked = true;
|
||||
}
|
||||
if (event.key === shiftKey) {
|
||||
shiftClicked = true;
|
||||
}
|
||||
});
|
||||
window.addEventListener("wheel", (event) => {
|
||||
if (event.ctrlKey) {
|
||||
wheel = true;
|
||||
controlClicked = true;
|
||||
}
|
||||
});
|
||||
window.addEventListener("dblclick", (event) => {
|
||||
if (event.ctrlKey) {
|
||||
dbclicked = true;
|
||||
}
|
||||
});
|
||||
window.addEventListener("keyup", (event) => {
|
||||
if (event.key === controlKey) {
|
||||
clicked = false;
|
||||
move = false;
|
||||
wheel = false;
|
||||
dbclicked = false;
|
||||
}
|
||||
});
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (event.key === controlKey) {
|
||||
stopDraw(canvas);
|
||||
enableZoom(canvas);
|
||||
}
|
||||
});
|
||||
window.addEventListener("keyup", (event) => {
|
||||
if (event.key === controlKey) {
|
||||
disableFunctions();
|
||||
handleToolChanges(activeTool);
|
||||
if (event.shiftKey) {
|
||||
shiftClicked = true;
|
||||
}
|
||||
});
|
||||
window.addEventListener(
|
||||
|
@ -108,10 +128,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (clicked && move && wheel && !dbclicked) {
|
||||
stopDraw(canvas);
|
||||
if (controlClicked) {
|
||||
disableFunctions();
|
||||
enableZoom(canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shiftClicked) {
|
||||
onWheelDragX(canvas, event);
|
||||
return;
|
||||
}
|
||||
|
||||
onWheelDrag(canvas, event);
|
||||
},
|
||||
{ passive: false },
|
||||
|
@ -153,6 +180,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
const disableFunctions = () => {
|
||||
stopDraw(canvas);
|
||||
disableZoom(canvas);
|
||||
disablePan(canvas);
|
||||
};
|
||||
|
||||
function changeOcclusionType(occlusionType: "all" | "one"): void {
|
||||
|
|
|
@ -10,8 +10,6 @@ import Hammer from "hammerjs";
|
|||
|
||||
import { getBoundingBox, redraw } from "./lib";
|
||||
|
||||
let isDragging = false;
|
||||
|
||||
const minScale = 0.5;
|
||||
const maxScale = 5;
|
||||
let zoomScale = 1;
|
||||
|
@ -19,6 +17,9 @@ export let currentScale = 1;
|
|||
|
||||
export const enableZoom = (canvas: fabric.Canvas) => {
|
||||
canvas.on("mouse:wheel", onMouseWheel);
|
||||
};
|
||||
|
||||
export const enablePan = (canvas: fabric.Canvas) => {
|
||||
canvas.on("mouse:down", onMouseDown);
|
||||
canvas.on("mouse:move", onMouseMove);
|
||||
canvas.on("mouse:up", onMouseUp);
|
||||
|
@ -26,6 +27,9 @@ export const enableZoom = (canvas: fabric.Canvas) => {
|
|||
|
||||
export const disableZoom = (canvas: fabric.Canvas) => {
|
||||
canvas.off("mouse:wheel", onMouseWheel);
|
||||
};
|
||||
|
||||
export const disablePan = (canvas: fabric.Canvas) => {
|
||||
canvas.off("mouse:down", onMouseDown);
|
||||
canvas.off("mouse:move", onMouseMove);
|
||||
canvas.off("mouse:up", onMouseUp);
|
||||
|
@ -98,7 +102,6 @@ const onMouseWheel = (opt) => {
|
|||
};
|
||||
|
||||
const onMouseDown = (opt) => {
|
||||
isDragging = true;
|
||||
const canvas = globalThis.canvas;
|
||||
canvas.discardActiveObject();
|
||||
const { e } = opt;
|
||||
|
@ -111,19 +114,17 @@ const onMouseDown = (opt) => {
|
|||
|
||||
export const onMouseMove = (opt) => {
|
||||
const canvas = globalThis.canvas;
|
||||
if (isDragging) {
|
||||
canvas.discardActiveObject();
|
||||
if (!canvas.viewportTransform) {
|
||||
return;
|
||||
}
|
||||
|
||||
// handle pinch zoom and pan for mobile devices
|
||||
if (onPinchZoom(opt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onDrag(canvas, opt);
|
||||
canvas.discardActiveObject();
|
||||
if (!canvas.viewportTransform) {
|
||||
return;
|
||||
}
|
||||
|
||||
// handle pinch zoom and pan for mobile devices
|
||||
if (onPinchZoom(opt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onDrag(canvas, opt);
|
||||
};
|
||||
|
||||
// initializes lastPosX and lastPosY because it is undefined in touchmove event
|
||||
|
@ -133,6 +134,17 @@ document.addEventListener("touchstart", (e) => {
|
|||
canvas.lastPosY = e.touches[0].clientY;
|
||||
});
|
||||
|
||||
// initializes lastPosX and lastPosY because it is undefined before mousemove event
|
||||
document.addEventListener("mousemove", (event) => {
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === " ") {
|
||||
const canvas = globalThis.canvas;
|
||||
canvas.lastPosX = event.clientX;
|
||||
canvas.lastPosY = event.clientY;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export const onPinchZoom = (opt): boolean => {
|
||||
const { e } = opt;
|
||||
const canvas = globalThis.canvas;
|
||||
|
@ -151,8 +163,8 @@ const onDrag = (canvas, opt) => {
|
|||
|
||||
vpt[4] += clientX - canvas.lastPosX;
|
||||
vpt[5] += clientY - canvas.lastPosY;
|
||||
canvas.lastPosX = clientX;
|
||||
canvas.lastPosY = clientY;
|
||||
canvas.lastPosX += clientX - canvas.lastPosX;
|
||||
canvas.lastPosY += clientY - canvas.lastPosY;
|
||||
constrainBoundsAroundBgImage(canvas);
|
||||
redraw(canvas);
|
||||
};
|
||||
|
@ -174,8 +186,18 @@ export const onWheelDrag = (canvas: fabric.Canvas, event: WheelEvent) => {
|
|||
redraw(canvas);
|
||||
};
|
||||
|
||||
export const onWheelDragX = (canvas: fabric.Canvas, event: WheelEvent) => {
|
||||
const delta = event.deltaY;
|
||||
const vpt = canvas.viewportTransform;
|
||||
canvas.lastPosY = event.clientY;
|
||||
vpt[4] -= delta;
|
||||
canvas.lastPosX -= delta;
|
||||
canvas.setViewportTransform(vpt);
|
||||
constrainBoundsAroundBgImage(canvas);
|
||||
redraw(canvas);
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
isDragging = false;
|
||||
const canvas = globalThis.canvas;
|
||||
canvas.setViewportTransform(canvas.viewportTransform);
|
||||
constrainBoundsAroundBgImage(canvas);
|
||||
|
|
Loading…
Reference in a new issue