@deepnoid/canvas 0.1.21 → 0.1.23

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.
@@ -7,10 +7,10 @@ import { usePanZoom } from '../hooks/usePanZoom';
7
7
  const AnnotatedCanvas = ({ image, coordinates, panZoomable = false, ZoomButton, resetOnImageChange = true, editable = false, onImageLoadError, onImageLoadSuccess, }) => {
8
8
  const canvasRef = useRef(null);
9
9
  const [displayCoordinates, setDisplayCoordinates] = useState();
10
- const { image: loadedImage, isLoading, error } = useImageLoader(image, 10000, onImageLoadSuccess, onImageLoadError);
10
+ const { image: loadedImage, isLoading, error, imageRef, } = useImageLoader(image, 10000, onImageLoadSuccess, onImageLoadError);
11
11
  const { moveX, moveY, zoom, initZoom, zoomX, zoomY, dx, dy, dw, dh, handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, handleMouseLeave, initCanvas, } = usePanZoom({
12
12
  canvasRef,
13
- image: loadedImage,
13
+ imageRef,
14
14
  panZoomable,
15
15
  resetOnImageChange,
16
16
  });
@@ -1,11 +1,11 @@
1
1
  import { RefObject, WheelEvent, MouseEvent } from 'react';
2
2
  type UsePanZoomProps = {
3
3
  canvasRef: RefObject<HTMLCanvasElement | null>;
4
- image: HTMLImageElement | null;
4
+ imageRef: RefObject<HTMLImageElement | null>;
5
5
  panZoomable?: boolean;
6
6
  resetOnImageChange?: boolean;
7
7
  };
8
- export declare const usePanZoom: ({ canvasRef, image, panZoomable, resetOnImageChange }: UsePanZoomProps) => {
8
+ export declare const usePanZoom: ({ canvasRef, imageRef, panZoomable, resetOnImageChange, }: UsePanZoomProps) => {
9
9
  moveX: number;
10
10
  moveY: number;
11
11
  zoom: number;
@@ -17,7 +17,7 @@ export declare const usePanZoom: ({ canvasRef, image, panZoomable, resetOnImageC
17
17
  dw: number;
18
18
  dh: number;
19
19
  handleWheel: (event: WheelEvent) => void;
20
- handleMouseDown: (event: MouseEvent) => false | undefined;
20
+ handleMouseDown: (event: MouseEvent) => void;
21
21
  handleMouseMove: (event: MouseEvent) => void;
22
22
  handleMouseUp: (event: MouseEvent) => void;
23
23
  handleMouseLeave: (event: MouseEvent) => void;
@@ -1,9 +1,9 @@
1
1
  'use client';
2
- import { useCallback, useEffect, useState, useRef } from 'react';
2
+ import { useCallback, useEffect, useState } from 'react';
3
3
  import { resolutionCanvas, drawCanvas, getMousePointTransform, canvasCenterPoint } from '../utils/graphic';
4
4
  import { MouseStatus } from '../enum/common';
5
5
  import useResizeObserver from './useResizeObserver';
6
- export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImageChange = true }) => {
6
+ export const usePanZoom = ({ canvasRef, imageRef, panZoomable = false, resetOnImageChange = true, }) => {
7
7
  const ZOOM_UNIT = 0.9;
8
8
  const MAX_ZOOM = 4;
9
9
  const MIN_ZOOM = 0.5;
@@ -20,8 +20,7 @@ export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImage
20
20
  const [moveY, setMoveY] = useState(0);
21
21
  const [status, setStatus] = useState('');
22
22
  const [imageOnloadCount, setImageOnloadCount] = useState(0);
23
- const [_imageInfo, _setImageInfo] = useState();
24
- const imageRef = useRef(new Image());
23
+ const [startMousePoint, setStartMousePoint] = useState();
25
24
  const calculatorZoomPoint = useCallback((canvasEl, movementX, movementY, dx, dy) => {
26
25
  let x = 0;
27
26
  let y = 0;
@@ -30,18 +29,15 @@ export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImage
30
29
  y = -dy - movementY + canvasEl.height / 2;
31
30
  }
32
31
  return { x, y };
33
- }, []);
34
- const calculateInitZoom = useCallback((image, canvasEl) => {
35
- if (canvasEl.clientWidth < canvasEl.clientHeight) {
36
- return canvasEl.clientWidth / canvasEl.clientHeight < image.width / image.height
37
- ? canvasEl.clientWidth / image.width
38
- : canvasEl.clientHeight / image.height;
39
- }
40
- else {
41
- return canvasEl.clientWidth / canvasEl.clientHeight > image.width / image.height
42
- ? canvasEl.clientHeight / image.height
43
- : canvasEl.clientWidth / image.width;
44
- }
32
+ }, [canvasRef]);
33
+ const calculateInitZoom = useCallback((canvasEl, image) => {
34
+ if (!image)
35
+ return 1;
36
+ const canvasRatio = canvasEl.clientWidth / canvasEl.clientHeight;
37
+ const imageRatio = image.naturalWidth / image.naturalHeight;
38
+ return canvasRatio < imageRatio
39
+ ? canvasEl.clientWidth / image.naturalWidth
40
+ : canvasEl.clientHeight / image.naturalHeight;
45
41
  }, []);
46
42
  const init = (canvasEl, image) => {
47
43
  const point = canvasCenterPoint(canvasEl, image);
@@ -51,7 +47,7 @@ export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImage
51
47
  setDh(image.height);
52
48
  setMoveX(0);
53
49
  setMoveY(0);
54
- const init_zoom = calculateInitZoom(image, canvasEl);
50
+ const init_zoom = calculateInitZoom(canvasEl, image);
55
51
  setZoom(init_zoom);
56
52
  setInitZoom(init_zoom);
57
53
  const zoomPoint = calculatorZoomPoint(canvasEl, 0, 0, point.x, point.y);
@@ -59,7 +55,7 @@ export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImage
59
55
  setZoomY(zoomPoint.y);
60
56
  };
61
57
  const initCanvas = () => {
62
- if (image) {
58
+ if (imageRef?.current) {
63
59
  const canvasEl = resolutionCanvas(canvasRef.current);
64
60
  if (canvasEl)
65
61
  init(canvasEl, imageRef.current);
@@ -67,94 +63,77 @@ export const usePanZoom = ({ canvasRef, image, panZoomable = false, resetOnImage
67
63
  }
68
64
  };
69
65
  useEffect(() => {
66
+ const image = imageRef?.current;
70
67
  if (image) {
71
- imageRef.current.src = image.src;
72
- imageRef.current.onload = () => {
73
- if (resetOnImageChange) {
74
- const canvasEl = resolutionCanvas(canvasRef.current);
75
- if (canvasEl)
76
- init(canvasEl, imageRef.current);
77
- }
78
- setImageOnloadCount((prev) => prev + 1);
79
- };
68
+ if (resetOnImageChange) {
69
+ const canvasEl = resolutionCanvas(canvasRef.current);
70
+ if (canvasEl)
71
+ init(canvasEl, image);
72
+ }
73
+ setImageOnloadCount((prev) => prev + 1);
80
74
  }
81
- }, [image]);
82
- const [startMousePoint, setStartMousePoint] = useState();
75
+ }, [imageRef?.current, resetOnImageChange]);
83
76
  useEffect(() => {
84
77
  const redraw = () => {
85
- if (canvasRef.current) {
78
+ if (canvasRef.current && imageRef?.current) {
86
79
  drawCanvas(moveX, moveY, zoomX, zoomY, zoom, dx, dy, resolutionCanvas(canvasRef.current), imageRef.current, true);
87
80
  }
88
81
  };
89
82
  redraw();
90
- }, [moveX, moveY, zoomX, zoomY, zoom, dx, dy, dw, dh, imageOnloadCount]);
83
+ }, [moveX, moveY, zoomX, zoomY, zoom, dx, dy, dw, dh, imageOnloadCount, canvasRef, imageRef]);
91
84
  useEffect(() => {
92
- if (image) {
93
- imageRef.current.src = image.src;
94
- const canvasEl = resolutionCanvas(canvasRef.current);
95
- if (canvasEl)
96
- init(canvasEl, imageRef.current);
85
+ if (!imageRef?.current)
86
+ return;
87
+ const canvasEl = resolutionCanvas(canvasRef.current);
88
+ if (canvasEl && !resetOnImageChange) {
89
+ init(canvasEl, imageRef.current);
97
90
  setImageOnloadCount((prev) => prev + 1);
98
91
  }
99
- }, [width, height]);
92
+ }, [width, height, resetOnImageChange, canvasRef, imageRef]);
100
93
  const handleWheel = (event) => {
101
- if (!panZoomable)
94
+ if (!panZoomable || !canvasRef.current || !imageRef?.current)
102
95
  return;
103
- if (canvasRef.current) {
104
- let calc_zoom = event.deltaY < 0 ? (zoom || 1) * (1 / ZOOM_UNIT) : (zoom || 1) * ZOOM_UNIT;
105
- if (initZoom * MAX_ZOOM < zoom * ZOOM_UNIT)
106
- calc_zoom = calc_zoom * ZOOM_UNIT;
107
- if (initZoom * MIN_ZOOM > zoom * ZOOM_UNIT)
108
- calc_zoom = calc_zoom * (1 / ZOOM_UNIT);
109
- const canvasEl = canvasRef.current;
110
- const zoomPoint = calculatorZoomPoint(canvasEl, moveX, moveY, dx, dy);
111
- setZoomX(zoomPoint.x);
112
- setZoomY(zoomPoint.y);
113
- setZoom(calc_zoom);
114
- }
96
+ let calc_zoom = event.deltaY < 0 ? (zoom || 1) * (1 / ZOOM_UNIT) : (zoom || 1) * ZOOM_UNIT;
97
+ if (initZoom * MAX_ZOOM < zoom * ZOOM_UNIT)
98
+ calc_zoom = calc_zoom * ZOOM_UNIT;
99
+ if (initZoom * MIN_ZOOM > zoom * ZOOM_UNIT)
100
+ calc_zoom = calc_zoom * (1 / ZOOM_UNIT);
101
+ const zoomPoint = calculatorZoomPoint(canvasRef.current, moveX, moveY, dx, dy);
102
+ setZoomX(zoomPoint.x);
103
+ setZoomY(zoomPoint.y);
104
+ setZoom(calc_zoom);
115
105
  };
116
106
  const handleMouseMove = (event) => {
117
- if (!panZoomable)
107
+ if (!panZoomable || status !== MouseStatus.MOVE || !canvasRef.current || !imageRef?.current)
118
108
  return;
119
- if (status === MouseStatus.MOVE) {
120
- if (canvasRef.current) {
121
- const canvasEl = canvasRef.current;
122
- const rect = canvasEl.getBoundingClientRect();
123
- const mouseX = event.clientX - rect.left;
124
- const mouseY = event.clientY - rect.top;
125
- const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvasEl);
126
- let x = mouse.x;
127
- let y = mouse.y;
128
- if (startMousePoint) {
129
- x = x - startMousePoint.x;
130
- y = y - startMousePoint.y;
131
- }
132
- setMoveX(moveX + x);
133
- setMoveY(moveY + y);
134
- const zoomPoint = calculatorZoomPoint(canvasEl, moveX + x, moveY + y, dx, dy);
135
- setZoomX(zoomPoint.x);
136
- setZoomY(zoomPoint.y);
137
- }
109
+ const canvasEl = canvasRef.current;
110
+ const rect = canvasEl.getBoundingClientRect();
111
+ const mouseX = event.clientX - rect.left;
112
+ const mouseY = event.clientY - rect.top;
113
+ const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvasEl);
114
+ let x = mouse.x;
115
+ let y = mouse.y;
116
+ if (startMousePoint) {
117
+ x -= startMousePoint.x;
118
+ y -= startMousePoint.y;
138
119
  }
120
+ setMoveX(moveX + x);
121
+ setMoveY(moveY + y);
122
+ const zoomPoint = calculatorZoomPoint(canvasEl, moveX + x, moveY + y, dx, dy);
123
+ setZoomX(zoomPoint.x);
124
+ setZoomY(zoomPoint.y);
139
125
  event.preventDefault();
140
126
  };
141
127
  const handleMouseDown = (event) => {
142
- if (!panZoomable)
143
- return false;
128
+ if (!panZoomable || !canvasRef.current || !imageRef?.current)
129
+ return;
144
130
  setStatus(MouseStatus.MOVE);
145
- if (canvasRef.current) {
146
- const canvasEl = canvasRef.current;
147
- const rect = canvasEl.getBoundingClientRect();
148
- const mouseX = event.clientX - rect.left;
149
- const mouseY = event.clientY - rect.top;
150
- const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvasEl);
151
- const x = mouse.x;
152
- const y = mouse.y;
153
- setStartMousePoint({
154
- x: x,
155
- y: y,
156
- });
157
- }
131
+ const canvasEl = canvasRef.current;
132
+ const rect = canvasEl.getBoundingClientRect();
133
+ const mouseX = event.clientX - rect.left;
134
+ const mouseY = event.clientY - rect.top;
135
+ const mouse = getMousePointTransform({ x: mouseX, y: mouseY }, { x: moveX, y: moveY }, { x: zoomX, y: zoomY }, { x: dx, y: dy }, zoom || 1, canvasEl);
136
+ setStartMousePoint({ x: mouse.x, y: mouse.y });
158
137
  event.preventDefault();
159
138
  };
160
139
  const handleMouseUp = (event) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepnoid/canvas",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",