remember pinch to zoom state when re-opening board
This commit is contained in:
@@ -227,16 +227,18 @@ export function localeCompare(a: string, b: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ui
|
// ui
|
||||||
export function implementPinchZoom(canvas: HTMLElement) {
|
export interface PinchToZoomData {
|
||||||
|
zoom: number;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
export function implementPinchZoom(canvas: HTMLElement, data: React.State<PinchToZoomData>) {
|
||||||
let pinching = false;
|
let pinching = false;
|
||||||
let dragging = false;
|
let dragging = false;
|
||||||
let lastElement: HTMLElement | undefined = undefined;
|
let lastElement: HTMLElement | undefined = undefined;
|
||||||
|
|
||||||
let initialDistance: number,
|
let initialDistance: number,
|
||||||
currentZoom: number,
|
|
||||||
initialZoom: number,
|
initialZoom: number,
|
||||||
currentX: number,
|
|
||||||
currentY: number,
|
|
||||||
initialX: number,
|
initialX: number,
|
||||||
initialY: number,
|
initialY: number,
|
||||||
initialTouchX: number,
|
initialTouchX: number,
|
||||||
@@ -245,11 +247,8 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
|||||||
function reset() {
|
function reset() {
|
||||||
initialDistance = 0;
|
initialDistance = 0;
|
||||||
|
|
||||||
currentZoom = 1;
|
|
||||||
initialZoom = 1;
|
initialZoom = 1;
|
||||||
|
|
||||||
currentX = 0;
|
|
||||||
currentY = 0;
|
|
||||||
initialX = 0;
|
initialX = 0;
|
||||||
initialY = 0;
|
initialY = 0;
|
||||||
initialTouchX = 0;
|
initialTouchX = 0;
|
||||||
@@ -272,41 +271,41 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
|||||||
const midpoint = (e: TouchEvent, direction: "x" | "y") =>
|
const midpoint = (e: TouchEvent, direction: "x" | "y") =>
|
||||||
(point(e, direction, 0) + point(e, direction, 1)) / 2;
|
(point(e, direction, 0) + point(e, direction, 1)) / 2;
|
||||||
|
|
||||||
function apply(factor: number, _offset?: [number, number]) {
|
function apply(zoom: number, _offset?: [number, number]) {
|
||||||
|
if (zoom < MIN) return apply(MIN, _offset);
|
||||||
|
if (zoom > MAX) return apply(5, _offset);
|
||||||
|
|
||||||
|
let {x, y} = data.value;
|
||||||
|
if (_offset) [x, y] = _offset;
|
||||||
|
|
||||||
|
data.value = {
|
||||||
|
zoom, x, y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.subscribe((data) => {
|
||||||
const el = element();
|
const el = element();
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (factor < MIN) return apply(MIN, _offset);
|
el.style.transform = `scale(${data.zoom.toString()}) translate(${data.x}px, ${data.y}px)`;
|
||||||
if (factor > MAX) return apply(5, _offset);
|
})
|
||||||
|
|
||||||
let x: number, y: number;
|
|
||||||
if (_offset) [x, y] = _offset;
|
|
||||||
else {
|
|
||||||
x = currentX;
|
|
||||||
y = currentY;
|
|
||||||
}
|
|
||||||
el.style.transform = `scale(${factor.toString()}) translate(${x}px, ${y}px)`;
|
|
||||||
currentX = x;
|
|
||||||
currentY = y;
|
|
||||||
currentZoom = factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.addEventListener("wheel", (event: WheelEvent) => {
|
canvas.addEventListener("wheel", (event: WheelEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
initialZoom = currentZoom;
|
initialZoom = data.value.zoom;
|
||||||
initialX = currentX;
|
initialX = data.value.x;
|
||||||
initialY = currentY;
|
initialY = data.value.y;
|
||||||
|
|
||||||
apply(currentZoom - event.deltaY * 0.005);
|
apply(data.value.zoom - event.deltaY * 0.005);
|
||||||
});
|
});
|
||||||
canvas.addEventListener("scroll", (event: Event) => {
|
canvas.addEventListener("scroll", (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
canvas.addEventListener("mousedown", (event: MouseEvent) => {
|
canvas.addEventListener("mousedown", (event: MouseEvent) => {
|
||||||
initialZoom = currentZoom;
|
initialZoom = data.value.zoom;
|
||||||
initialX = currentX;
|
initialX = data.value.x;
|
||||||
initialY = currentY;
|
initialY = data.value.y;
|
||||||
initialTouchX = event.clientX;
|
initialTouchX = event.clientX;
|
||||||
initialTouchY = event.clientY;
|
initialTouchY = event.clientY;
|
||||||
dragging = true;
|
dragging = true;
|
||||||
@@ -316,7 +315,7 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
|||||||
})
|
})
|
||||||
canvas.addEventListener("mousemove", (event: MouseEvent) => {
|
canvas.addEventListener("mousemove", (event: MouseEvent) => {
|
||||||
if (!dragging) return;
|
if (!dragging) return;
|
||||||
apply(currentZoom, [
|
apply(data.value.zoom, [
|
||||||
initialX +
|
initialX +
|
||||||
(event.clientX - initialTouchX) / initialZoom,
|
(event.clientX - initialTouchX) / initialZoom,
|
||||||
initialY +
|
initialY +
|
||||||
@@ -332,9 +331,9 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
|||||||
if (lastElement != undefined && lastElement != el) reset();
|
if (lastElement != undefined && lastElement != el) reset();
|
||||||
lastElement = el;
|
lastElement = el;
|
||||||
|
|
||||||
initialZoom = currentZoom;
|
initialZoom = data.value.zoom;
|
||||||
initialX = currentX;
|
initialX = data.value.x;
|
||||||
initialY = currentY;
|
initialY = data.value.y;
|
||||||
|
|
||||||
if (event.touches.length != 2) {
|
if (event.touches.length != 2) {
|
||||||
pinching = false;
|
pinching = false;
|
||||||
@@ -350,7 +349,7 @@ export function implementPinchZoom(canvas: HTMLElement) {
|
|||||||
});
|
});
|
||||||
canvas.addEventListener("touchmove", (event: TouchEvent) => {
|
canvas.addEventListener("touchmove", (event: TouchEvent) => {
|
||||||
if (!pinching) {
|
if (!pinching) {
|
||||||
apply(currentZoom, [
|
apply(data.value.zoom, [
|
||||||
initialX +
|
initialX +
|
||||||
(event.touches[0].clientX - initialTouchX) / initialZoom,
|
(event.touches[0].clientX - initialTouchX) / initialZoom,
|
||||||
initialY +
|
initialY +
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function BoardPage(
|
|||||||
const wrapper = (
|
const wrapper = (
|
||||||
<div class="content main-content" children:set={pages}></div>
|
<div class="content main-content" children:set={pages}></div>
|
||||||
);
|
);
|
||||||
Utility.implementPinchZoom(wrapper);
|
Utility.implementPinchZoom(wrapper, boardViewModel.pinchToZoomData);
|
||||||
|
|
||||||
// task modal
|
// task modal
|
||||||
const taskSettingsModal = React.createProxyState(
|
const taskSettingsModal = React.createProxyState(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import BoardsAndTasksModel, {
|
|||||||
BoardInfoFileContent,
|
BoardInfoFileContent,
|
||||||
TaskFileContent,
|
TaskFileContent,
|
||||||
} from "../../Model/Files/boardsAndTasksModel";
|
} from "../../Model/Files/boardsAndTasksModel";
|
||||||
|
import {PinchToZoomData} from "../../Model/Utility/utility";
|
||||||
|
|
||||||
export default class BoardViewModel extends TaskContainingPageViewModel {
|
export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||||
// state
|
// state
|
||||||
@@ -33,6 +34,8 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
|
|||||||
new React.ListState();
|
new React.ListState();
|
||||||
isFilterActive: React.State<boolean>;
|
isFilterActive: React.State<boolean>;
|
||||||
|
|
||||||
|
pinchToZoomData: React.State<PinchToZoomData> = new React.State({zoom: 1, x: 0, y: 0});
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
getBasePath = (): string[] => {
|
getBasePath = (): string[] => {
|
||||||
return [
|
return [
|
||||||
|
|||||||
Reference in New Issue
Block a user