@deepnoid/canvas 0.1.30 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import Canvas from './Canvas';
|
|
5
5
|
import { usePanZoom } from '../hooks/usePanZoom';
|
|
@@ -8,117 +8,73 @@ import { drawCanvas, resolutionCanvas } from '../utils/graphic';
|
|
|
8
8
|
const AnnotatedCanvas = ({ image, coordinates, panZoomable = false, ZoomButton, resetOnImageChange = true, editable = false, timeout = 10000, onImageLoadSuccess, onImageLoadError, }) => {
|
|
9
9
|
const canvasRef = useRef(null);
|
|
10
10
|
const imageRef = useRef(new Image());
|
|
11
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
12
|
-
const [isError, setIsError] = useState(false);
|
|
13
11
|
const { width, height } = useResizeObserver({ ref: canvasRef });
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
imageRef,
|
|
17
|
-
panZoomable,
|
|
18
|
-
});
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
const redraw = () => {
|
|
21
|
-
if (canvasRef.current) {
|
|
22
|
-
drawCanvas(moveX, moveY, zoomX, zoomY, zoom, dx, dy, resolutionCanvas(canvasRef.current), imageRef.current, true);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
redraw();
|
|
26
|
-
}, [moveX, moveY, zoomX, zoomY, zoom, dx, dy, dw, dh, imageOnloadCount]);
|
|
27
|
-
// --------
|
|
28
|
-
// useEffect(() => {
|
|
29
|
-
// if (!imageRef?.current || !canvasRef?.current || !width || !height) return;
|
|
30
|
-
// const canvasEl = resolutionCanvas(canvasRef.current);
|
|
31
|
-
// if (!canvasEl) return;
|
|
32
|
-
// const isFirstLoad = imageOnloadCount === 0;
|
|
33
|
-
// if (isFirstLoad) {
|
|
34
|
-
// init(canvasEl, imageRef.current);
|
|
35
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
36
|
-
// return;
|
|
37
|
-
// }
|
|
38
|
-
// if (resetOnImageChange) {
|
|
39
|
-
// init(canvasEl, imageRef.current);
|
|
40
|
-
// } else {
|
|
41
|
-
// drawCanvas(moveX, moveY, zoomX, zoomY, zoom, dx, dy, canvasEl, imageRef.current, true);
|
|
42
|
-
// }
|
|
43
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
44
|
-
// }, [imageRef?.current, width, height, resetOnImageChange]);
|
|
45
|
-
// ----------
|
|
12
|
+
const [displayCoordinates, setDisplayCoordinates] = useState();
|
|
13
|
+
const { canvasState, init, initCanvas, clearCanvas, preserveZoomAndPosition, handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, handleMouseLeave, imageOnloadCount, setImageOnloadCount, } = usePanZoom({ canvasRef, imageRef, panZoomable });
|
|
46
14
|
useEffect(() => {
|
|
47
15
|
if (!image || image.trim() === '') {
|
|
48
|
-
setIsLoading(false);
|
|
49
|
-
setIsError(false);
|
|
50
16
|
clearCanvas();
|
|
51
17
|
return;
|
|
52
18
|
}
|
|
53
|
-
setIsLoading(true);
|
|
54
19
|
imageRef.current.src = image;
|
|
55
20
|
imageRef.current.onload = () => {
|
|
56
|
-
console.log('> ======================= useEffect onload ============================');
|
|
57
|
-
setIsLoading(false);
|
|
58
|
-
setIsError(false);
|
|
59
21
|
onImageLoadSuccess?.();
|
|
60
|
-
// const canvas = resolutionCanvas(canvasRef.current);
|
|
61
|
-
// if (canvas) init(canvas, imageRef.current);
|
|
62
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
63
|
-
console.log('> canvasRef.current : ', canvasRef.current);
|
|
64
22
|
const canvas = resolutionCanvas(canvasRef.current);
|
|
65
|
-
console.log(' > canvas :', canvas);
|
|
66
23
|
if (!canvas)
|
|
67
24
|
return;
|
|
68
|
-
if (resetOnImageChange)
|
|
25
|
+
if (resetOnImageChange) {
|
|
69
26
|
init(canvas, imageRef.current);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
preserveZoomAndPosition(canvas, imageRef.current, canvasState.zoom / canvasState.initZoom);
|
|
30
|
+
}
|
|
70
31
|
setImageOnloadCount((prev) => prev + 1);
|
|
71
|
-
|
|
72
|
-
// // prevImageRef.current = image;
|
|
73
|
-
// prevImageRef.current = imageRef.current.src;
|
|
74
|
-
// const canvas = resolutionCanvas(canvasRef.current);
|
|
75
|
-
// const isFirstLoad = imageOnloadCount === 0;
|
|
76
|
-
// console.log('> onload - isFirstLoad : ', isFirstLoad);
|
|
77
|
-
// // if (canvas && isFirstLoad) {
|
|
78
|
-
// // init(canvas, imageRef.current);
|
|
79
|
-
// // setImageOnloadCount((prev) => prev + 1);
|
|
80
|
-
// // }
|
|
81
|
-
// if (!canvas) return;
|
|
82
|
-
// if (isFirstLoad) {
|
|
83
|
-
// init(canvas, imageRef.current);
|
|
84
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
85
|
-
// return;
|
|
86
|
-
// }
|
|
87
|
-
// console.log('> !!!!!!!!!!!!!!!! resetOnImageChange : ', resetOnImageChange);
|
|
88
|
-
// if (resetOnImageChange) {
|
|
89
|
-
// init(canvas, imageRef.current);
|
|
90
|
-
// } else {
|
|
91
|
-
// // drawCanvas(moveX, moveY, zoomX, zoomY, zoom, dx, dy, canvas, imageRef.current, true);
|
|
92
|
-
// }
|
|
93
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
94
|
-
// // if (canvas) init(canvas, imageRef.current);
|
|
95
|
-
// }
|
|
96
|
-
// setImageOnloadCount((prev) => prev + 1);
|
|
32
|
+
setDisplayCoordinates(coordinates);
|
|
97
33
|
};
|
|
98
34
|
imageRef.current.onerror = () => {
|
|
99
|
-
setIsLoading(false);
|
|
100
|
-
setIsError(true);
|
|
101
35
|
const err = new Error(`Failed to load image: ${image}`);
|
|
102
36
|
onImageLoadError?.(err);
|
|
103
37
|
clearCanvas();
|
|
38
|
+
setDisplayCoordinates([]);
|
|
104
39
|
};
|
|
105
|
-
}, [image,
|
|
40
|
+
}, [image, resetOnImageChange]);
|
|
106
41
|
useEffect(() => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const canvas = resolutionCanvas(canvasRef.current);
|
|
112
|
-
if (canvas)
|
|
113
|
-
init(canvas, imageRef.current);
|
|
114
|
-
setImageOnloadCount((prev) => prev + 1);
|
|
115
|
-
}
|
|
42
|
+
if (image && width && height) {
|
|
43
|
+
const canvas = resolutionCanvas(canvasRef.current);
|
|
44
|
+
if (canvas)
|
|
45
|
+
init(canvas, imageRef.current);
|
|
116
46
|
}
|
|
117
47
|
}, [width, height]);
|
|
118
|
-
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!canvasRef.current)
|
|
50
|
+
return;
|
|
51
|
+
const redraw = (canvas) => {
|
|
52
|
+
drawCanvas(canvasState.moveX, canvasState.moveY, canvasState.zoomX, canvasState.zoomY, canvasState.zoom, canvasState.dx, canvasState.dy, canvas, imageRef.current, true);
|
|
53
|
+
};
|
|
54
|
+
const canvas = resolutionCanvas(canvasRef.current);
|
|
55
|
+
if (canvas)
|
|
56
|
+
redraw(canvas);
|
|
57
|
+
}, [canvasState, imageOnloadCount]);
|
|
58
|
+
return (_jsx("div", { style: { width: '100%', height: '100%', display: 'flex', flex: 1 }, children: _jsxs("div", { onWheel: handleWheel, onMouseMove: handleMouseMove, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onMouseLeave: handleMouseLeave, style: {
|
|
119
59
|
flex: 1,
|
|
120
60
|
position: 'relative',
|
|
121
61
|
cursor: panZoomable ? 'grab' : 'default',
|
|
122
|
-
}, children:
|
|
62
|
+
}, children: [_jsx("canvas", { ref: canvasRef, style: {
|
|
63
|
+
position: 'absolute',
|
|
64
|
+
width: '100%',
|
|
65
|
+
height: '100%',
|
|
66
|
+
left: 0,
|
|
67
|
+
top: 0,
|
|
68
|
+
} }), _jsx(Canvas, { ...canvasState,
|
|
69
|
+
// moveX={canvasState.moveX}
|
|
70
|
+
// moveY={canvasState.moveY}
|
|
71
|
+
// zoomX={canvasState.zoomX}
|
|
72
|
+
// zoomY={canvasState.zoomY}
|
|
73
|
+
// zoom={canvasState.zoom}
|
|
74
|
+
// dx={canvasState.dx}
|
|
75
|
+
// dy={canvasState.dy}
|
|
76
|
+
// dw={canvasState.dw}
|
|
77
|
+
// dh={canvasState.dh}
|
|
78
|
+
coordinates: displayCoordinates, editable: editable }), ZoomButton && canvasState.initZoom > 0 && (_jsx(ZoomButton, { onClick: initCanvas, children: `${Math.round((canvasState.zoom / canvasState.initZoom) * 100)}%` }))] }) }));
|
|
123
79
|
};
|
|
124
80
|
export default AnnotatedCanvas;
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { RefObject, WheelEvent, MouseEvent } from 'react';
|
|
2
|
+
type CanvasState = {
|
|
3
|
+
dx: number;
|
|
4
|
+
dy: number;
|
|
5
|
+
dw: number;
|
|
6
|
+
dh: number;
|
|
7
|
+
moveX: number;
|
|
8
|
+
moveY: number;
|
|
9
|
+
zoomX: number;
|
|
10
|
+
zoomY: number;
|
|
11
|
+
zoom: number;
|
|
12
|
+
initZoom: number;
|
|
13
|
+
};
|
|
2
14
|
type UsePanZoomProps = {
|
|
3
15
|
canvasRef: RefObject<HTMLCanvasElement | null>;
|
|
4
16
|
imageRef: RefObject<HTMLImageElement>;
|
|
5
17
|
panZoomable?: boolean;
|
|
6
18
|
};
|
|
7
19
|
export declare function usePanZoom({ canvasRef, imageRef, panZoomable }: UsePanZoomProps): {
|
|
8
|
-
|
|
9
|
-
moveY: number;
|
|
10
|
-
zoom: number;
|
|
11
|
-
initZoom: number;
|
|
12
|
-
zoomX: number;
|
|
13
|
-
zoomY: number;
|
|
14
|
-
dx: number;
|
|
15
|
-
dy: number;
|
|
16
|
-
dw: number;
|
|
17
|
-
dh: number;
|
|
20
|
+
canvasState: CanvasState;
|
|
18
21
|
imageOnloadCount: number;
|
|
19
22
|
setImageOnloadCount: import("react").Dispatch<import("react").SetStateAction<number>>;
|
|
20
23
|
init: (canvas: HTMLCanvasElement, image: HTMLImageElement) => void;
|
|
21
24
|
initCanvas: () => void;
|
|
22
25
|
clearCanvas: () => void;
|
|
26
|
+
preserveZoomAndPosition: (canvas: HTMLCanvasElement, image: HTMLImageElement, zoomRatio: number) => void;
|
|
23
27
|
handleWheel: (event: WheelEvent) => void;
|
|
24
28
|
handleMouseDown: (event: MouseEvent) => void;
|
|
25
29
|
handleMouseMove: (event: MouseEvent) => void;
|
package/dist/hooks/usePanZoom.js
CHANGED
|
@@ -1,89 +1,94 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
import { resolutionCanvas, getMousePointTransform, canvasCenterPoint } from '../utils/graphic';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { resolutionCanvas, getMousePointTransform, canvasCenterPoint, calculatorZoomPoint, calculateInitZoom, } from '../utils/graphic';
|
|
4
4
|
import { MouseStatus } from '../enum/common';
|
|
5
5
|
export function usePanZoom({ canvasRef, imageRef, panZoomable = false }) {
|
|
6
6
|
const ZOOM_UNIT = 0.9;
|
|
7
7
|
const MAX_ZOOM = 4;
|
|
8
8
|
const MIN_ZOOM = 0.5;
|
|
9
|
-
const [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const [canvasState, setCanvasState] = useState({
|
|
10
|
+
dx: 0,
|
|
11
|
+
dy: 0,
|
|
12
|
+
dw: 0,
|
|
13
|
+
dh: 0,
|
|
14
|
+
moveX: 0,
|
|
15
|
+
moveY: 0,
|
|
16
|
+
zoomX: 0,
|
|
17
|
+
zoomY: 0,
|
|
18
|
+
zoom: 0,
|
|
19
|
+
initZoom: 0,
|
|
20
|
+
});
|
|
19
21
|
const [status, setStatus] = useState('');
|
|
20
22
|
const [imageOnloadCount, setImageOnloadCount] = useState(0);
|
|
21
23
|
const [startMousePoint, setStartMousePoint] = useState();
|
|
22
|
-
const calculatorZoomPoint = useCallback((canvas, movementX, movementY, dx, dy) => {
|
|
23
|
-
let x = 0;
|
|
24
|
-
let y = 0;
|
|
25
|
-
if (canvas) {
|
|
26
|
-
x = -dx - movementX + canvas.width / 2;
|
|
27
|
-
y = -dy - movementY + canvas.height / 2;
|
|
28
|
-
}
|
|
29
|
-
return { x, y };
|
|
30
|
-
}, []);
|
|
31
|
-
const calculateInitZoom = useCallback((canvas, image) => {
|
|
32
|
-
if (!canvas || !image)
|
|
33
|
-
return 1;
|
|
34
|
-
const canvasRatio = canvas.clientWidth / canvas.clientHeight;
|
|
35
|
-
const imageRatio = image.naturalWidth / image.naturalHeight;
|
|
36
|
-
return canvasRatio < imageRatio
|
|
37
|
-
? canvas.clientWidth / image.naturalWidth
|
|
38
|
-
: canvas.clientHeight / image.naturalHeight;
|
|
39
|
-
}, []);
|
|
40
24
|
const init = (canvas, image) => {
|
|
41
|
-
if (!canvas || !image)
|
|
42
|
-
return;
|
|
43
25
|
const point = canvasCenterPoint(canvas, image);
|
|
44
|
-
setDx(point.x);
|
|
45
|
-
setDy(point.y);
|
|
46
|
-
setDw(image.width);
|
|
47
|
-
setDh(image.height);
|
|
48
|
-
setMoveX(0);
|
|
49
|
-
setMoveY(0);
|
|
50
|
-
const init_zoom = calculateInitZoom(canvas, image);
|
|
51
|
-
setZoom(init_zoom);
|
|
52
|
-
setInitZoom(init_zoom);
|
|
53
26
|
const zoomPoint = calculatorZoomPoint(canvas, 0, 0, point.x, point.y);
|
|
54
|
-
|
|
55
|
-
|
|
27
|
+
const initZoomValue = calculateInitZoom(canvas, image);
|
|
28
|
+
setCanvasState({
|
|
29
|
+
dx: point.x,
|
|
30
|
+
dy: point.y,
|
|
31
|
+
dw: image.width,
|
|
32
|
+
dh: image.height,
|
|
33
|
+
moveX: 0,
|
|
34
|
+
moveY: 0,
|
|
35
|
+
zoomX: zoomPoint.x,
|
|
36
|
+
zoomY: zoomPoint.y,
|
|
37
|
+
zoom: initZoomValue,
|
|
38
|
+
initZoom: initZoomValue,
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const preserveZoomAndPosition = (canvas, image, zoomRatio) => {
|
|
42
|
+
const prevZoomRatio = zoomRatio || 1;
|
|
43
|
+
const point = canvasCenterPoint(canvas, image);
|
|
44
|
+
const newInitZoom = calculateInitZoom(canvas, image);
|
|
45
|
+
const zoomPoint = calculatorZoomPoint(canvas, canvasState.moveX, canvasState.moveY, point.x, point.y);
|
|
46
|
+
setCanvasState({
|
|
47
|
+
dx: point.x,
|
|
48
|
+
dy: point.y,
|
|
49
|
+
dw: image.width,
|
|
50
|
+
dh: image.height,
|
|
51
|
+
moveX: canvasState.moveX,
|
|
52
|
+
moveY: canvasState.moveY,
|
|
53
|
+
zoomX: zoomPoint.x,
|
|
54
|
+
zoomY: zoomPoint.y,
|
|
55
|
+
zoom: newInitZoom * prevZoomRatio,
|
|
56
|
+
initZoom: newInitZoom,
|
|
57
|
+
});
|
|
56
58
|
};
|
|
57
59
|
const initCanvas = () => {
|
|
58
|
-
if (!canvasRef.current
|
|
60
|
+
if (!canvasRef.current)
|
|
59
61
|
return;
|
|
60
62
|
const canvas = resolutionCanvas(canvasRef.current);
|
|
61
|
-
if (canvas)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
if (!canvas)
|
|
64
|
+
return;
|
|
65
|
+
init(canvas, imageRef.current);
|
|
66
|
+
setImageOnloadCount((prev) => prev + 1);
|
|
65
67
|
};
|
|
66
68
|
const clearCanvas = () => {
|
|
67
69
|
if (!canvasRef.current)
|
|
68
70
|
return;
|
|
69
71
|
const canvas = resolutionCanvas(canvasRef.current);
|
|
70
|
-
if (canvas)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
if (!canvas)
|
|
73
|
+
return;
|
|
74
|
+
const ctx = canvas.getContext('2d');
|
|
75
|
+
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
|
74
76
|
};
|
|
75
77
|
const handleWheel = (event) => {
|
|
76
|
-
if (!panZoomable || !canvasRef.current)
|
|
78
|
+
if (!panZoomable || !canvasRef.current || canvasState.initZoom <= 0)
|
|
77
79
|
return;
|
|
78
|
-
let
|
|
79
|
-
if (initZoom * MAX_ZOOM < zoom * ZOOM_UNIT)
|
|
80
|
-
|
|
81
|
-
if (initZoom * MIN_ZOOM > zoom * ZOOM_UNIT)
|
|
82
|
-
|
|
83
|
-
const zoomPoint = calculatorZoomPoint(canvasRef.current, moveX, moveY, dx, dy);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
let calcZoom = event.deltaY < 0 ? canvasState.zoom * (1 / ZOOM_UNIT) : canvasState.zoom * ZOOM_UNIT;
|
|
81
|
+
if (canvasState.initZoom * MAX_ZOOM < canvasState.zoom * ZOOM_UNIT)
|
|
82
|
+
calcZoom = calcZoom * ZOOM_UNIT;
|
|
83
|
+
if (canvasState.initZoom * MIN_ZOOM > canvasState.zoom * ZOOM_UNIT)
|
|
84
|
+
calcZoom = calcZoom * (1 / ZOOM_UNIT);
|
|
85
|
+
const zoomPoint = calculatorZoomPoint(canvasRef.current, canvasState.moveX, canvasState.moveY, canvasState.dx, canvasState.dy);
|
|
86
|
+
setCanvasState({
|
|
87
|
+
...canvasState,
|
|
88
|
+
zoomX: zoomPoint.x,
|
|
89
|
+
zoomY: zoomPoint.y,
|
|
90
|
+
zoom: calcZoom,
|
|
91
|
+
});
|
|
87
92
|
};
|
|
88
93
|
const handleMouseMove = (event) => {
|
|
89
94
|
if (!panZoomable || !canvasRef.current || status !== MouseStatus.MOVE)
|
|
@@ -92,18 +97,21 @@ export function usePanZoom({ canvasRef, imageRef, panZoomable = false }) {
|
|
|
92
97
|
const rect = canvas.getBoundingClientRect();
|
|
93
98
|
const mouseX = event.clientX - rect.left;
|
|
94
99
|
const mouseY = event.clientY - rect.top;
|
|
95
|
-
const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvas);
|
|
100
|
+
const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: canvasState.moveX, y: canvasState.moveY }, { x: canvasState.zoomX, y: canvasState.zoomY }, { x: canvasState.dx, y: canvasState.dy }, canvasState.zoom || 1, canvas);
|
|
96
101
|
let x = mouse.x;
|
|
97
102
|
let y = mouse.y;
|
|
98
103
|
if (startMousePoint) {
|
|
99
104
|
x -= startMousePoint.x;
|
|
100
105
|
y -= startMousePoint.y;
|
|
101
106
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
const zoomPoint = calculatorZoomPoint(canvas, canvasState.moveX + x, canvasState.moveY + y, canvasState.dx, canvasState.dy);
|
|
108
|
+
setCanvasState({
|
|
109
|
+
...canvasState,
|
|
110
|
+
moveX: canvasState.moveX + x,
|
|
111
|
+
moveY: canvasState.moveY + y,
|
|
112
|
+
zoomX: zoomPoint.x,
|
|
113
|
+
zoomY: zoomPoint.y,
|
|
114
|
+
});
|
|
107
115
|
event.preventDefault();
|
|
108
116
|
};
|
|
109
117
|
const handleMouseDown = (event) => {
|
|
@@ -114,7 +122,7 @@ export function usePanZoom({ canvasRef, imageRef, panZoomable = false }) {
|
|
|
114
122
|
const rect = canvas.getBoundingClientRect();
|
|
115
123
|
const mouseX = event.clientX - rect.left;
|
|
116
124
|
const mouseY = event.clientY - rect.top;
|
|
117
|
-
const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvas);
|
|
125
|
+
const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: canvasState.moveX, y: canvasState.moveY }, { x: canvasState.zoomX, y: canvasState.zoomY }, { x: canvasState.dx, y: canvasState.dy }, canvasState.zoom || 1, canvas);
|
|
118
126
|
setStartMousePoint({ x: mouse.x, y: mouse.y });
|
|
119
127
|
event.preventDefault();
|
|
120
128
|
};
|
|
@@ -131,21 +139,13 @@ export function usePanZoom({ canvasRef, imageRef, panZoomable = false }) {
|
|
|
131
139
|
event.preventDefault();
|
|
132
140
|
};
|
|
133
141
|
return {
|
|
134
|
-
|
|
135
|
-
moveY,
|
|
136
|
-
zoom,
|
|
137
|
-
initZoom,
|
|
138
|
-
zoomX,
|
|
139
|
-
zoomY,
|
|
140
|
-
dx,
|
|
141
|
-
dy,
|
|
142
|
-
dw,
|
|
143
|
-
dh,
|
|
142
|
+
canvasState,
|
|
144
143
|
imageOnloadCount,
|
|
145
144
|
setImageOnloadCount,
|
|
146
145
|
init,
|
|
147
146
|
initCanvas,
|
|
148
147
|
clearCanvas,
|
|
148
|
+
preserveZoomAndPosition,
|
|
149
149
|
handleWheel,
|
|
150
150
|
handleMouseDown,
|
|
151
151
|
handleMouseMove,
|
|
@@ -14,14 +14,14 @@ const useResizeObserver = (opts = {}) => {
|
|
|
14
14
|
didUnmount.current = true;
|
|
15
15
|
};
|
|
16
16
|
}, []);
|
|
17
|
-
const refCallback = useResolvedElement(useCallback(element => {
|
|
17
|
+
const refCallback = useResolvedElement(useCallback((element) => {
|
|
18
18
|
if (!resizeObserverRef.current ||
|
|
19
19
|
resizeObserverRef.current.box !== opts.box ||
|
|
20
20
|
resizeObserverRef.current.round !== round) {
|
|
21
21
|
resizeObserverRef.current = {
|
|
22
22
|
box: opts.box,
|
|
23
23
|
round,
|
|
24
|
-
instance: new ResizeObserver(entries => {
|
|
24
|
+
instance: new ResizeObserver((entries) => {
|
|
25
25
|
const entry = entries[0];
|
|
26
26
|
const boxProp = opts.box === 'border-box'
|
|
27
27
|
? 'borderBoxSize'
|
|
@@ -102,7 +102,7 @@ function useResolvedElement(subscriber, refOrElement) {
|
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
}, []);
|
|
105
|
-
return useCallback(element => {
|
|
105
|
+
return useCallback((element) => {
|
|
106
106
|
cbElementRef.current = element;
|
|
107
107
|
evaluateSubscription();
|
|
108
108
|
}, [evaluateSubscription]);
|
package/dist/utils/graphic.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ export declare const canvasCenterPoint: (canvas: HTMLCanvasElement, image: HTMLI
|
|
|
3
3
|
x: number;
|
|
4
4
|
y: number;
|
|
5
5
|
};
|
|
6
|
+
export declare const calculatorZoomPoint: (canvas: HTMLCanvasElement, movementX: number, movementY: number, dx: number, dy: number) => {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
export declare const calculateInitZoom: (canvas: HTMLCanvasElement, image: HTMLImageElement) => number;
|
|
6
11
|
export declare const drawCanvas: (moveX: number, moveY: number, zoomX: number, zoomY: number, zoom: number, dx: number, dy: number, canvas_el?: HTMLCanvasElement, image?: HTMLImageElement, isClear?: boolean) => void;
|
|
7
12
|
export declare const drawRect: (context: CanvasRenderingContext2D, coordinate: Coordinate) => void;
|
|
8
13
|
export declare const setRectangleStyle: (context: CanvasRenderingContext2D, coordinate: Coordinate) => void;
|
package/dist/utils/graphic.js
CHANGED
|
@@ -5,6 +5,22 @@ export const canvasCenterPoint = (canvas, image) => {
|
|
|
5
5
|
const centerY = canvas.height / 2 - image.height / 2;
|
|
6
6
|
return { x: centerX, y: centerY };
|
|
7
7
|
};
|
|
8
|
+
export const calculatorZoomPoint = (canvas, movementX, movementY, dx, dy) => {
|
|
9
|
+
let x = 0;
|
|
10
|
+
let y = 0;
|
|
11
|
+
if (canvas) {
|
|
12
|
+
x = -dx - movementX + canvas.width / 2;
|
|
13
|
+
y = -dy - movementY + canvas.height / 2;
|
|
14
|
+
}
|
|
15
|
+
return { x, y };
|
|
16
|
+
};
|
|
17
|
+
export const calculateInitZoom = (canvas, image) => {
|
|
18
|
+
if (!canvas || !image.naturalWidth)
|
|
19
|
+
return 1;
|
|
20
|
+
const canvasRatio = canvas.clientWidth / canvas.clientHeight;
|
|
21
|
+
const imageRatio = image.naturalWidth / image.naturalHeight;
|
|
22
|
+
return canvasRatio < imageRatio ? canvas.clientWidth / image.naturalWidth : canvas.clientHeight / image.naturalHeight;
|
|
23
|
+
};
|
|
8
24
|
// [캔버스] 그리기
|
|
9
25
|
export const drawCanvas = (moveX, moveY, zoomX, zoomY, zoom, dx, dy, canvas_el, image, isClear) => {
|
|
10
26
|
if (canvas_el) {
|