@searpent/react-image-annotate 2.0.75 → 2.0.77

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.
Files changed (224) hide show
  1. package/.babelrc +6 -0
  2. package/.env +1 -0
  3. package/.flowconfig +2 -0
  4. package/.github/workflows/release-on-master.yml +32 -0
  5. package/.github/workflows/test.yml +16 -0
  6. package/.prettierrc +3 -0
  7. package/.releaserc.js +18 -0
  8. package/.storybook/addons.js +2 -0
  9. package/.storybook/config.js +16 -0
  10. package/LICENSE +21 -0
  11. package/package.json +1 -1
  12. package/public/favicon.ico +0 -0
  13. package/public/index.html +38 -0
  14. package/src/Annotator/bike-pic.png +0 -0
  15. package/src/Annotator/bike-pic2.png +0 -0
  16. package/src/Annotator/dab-keyframes.story.json +1 -0
  17. package/src/Annotator/exampleImages.js +48 -0
  18. package/src/Annotator/examplePhotos.js +7603 -0
  19. package/src/Annotator/index.js +380 -0
  20. package/src/Annotator/index.story.js +899 -0
  21. package/src/Annotator/poses.story.js +150 -0
  22. package/src/Annotator/reducers/combine-reducers.js +7 -0
  23. package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +53 -0
  24. package/{Annotator → src/Annotator}/reducers/fix-twisted.js +5 -3
  25. package/src/Annotator/reducers/general-reducer.js +1228 -0
  26. package/src/Annotator/reducers/get-active-image.js +21 -0
  27. package/src/Annotator/reducers/get-implied-video-regions.js +115 -0
  28. package/src/Annotator/reducers/history-handler.js +60 -0
  29. package/src/Annotator/reducers/image-reducer.js +23 -0
  30. package/src/Annotator/reducers/video-reducer.js +85 -0
  31. package/src/Annotator/video.story.js +51 -0
  32. package/src/ClassSelectionMenu/index.js +112 -0
  33. package/src/Crosshairs/index.js +64 -0
  34. package/src/DebugSidebarBox/index.js +36 -0
  35. package/src/DemoSite/Editor.js +235 -0
  36. package/src/DemoSite/ErrorBoundaryDialog.js +34 -0
  37. package/src/DemoSite/index.js +41 -0
  38. package/src/DemoSite/index.story.js +10 -0
  39. package/src/DemoSite/simple-segmentation-example.json +572 -0
  40. package/{Editor → src/Editor}/annotation-plugin/annotation.css +20 -0
  41. package/src/Editor/annotation-plugin/annotation.js +546 -0
  42. package/src/Editor/index.js +50 -0
  43. package/src/Editor/readOnly.js +31 -0
  44. package/{Editor → src/Editor}/tools.js +3 -2
  45. package/src/Errorer/index.js +13 -0
  46. package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
  47. package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
  48. package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
  49. package/src/FullImageSegmentationAnnotator/index.js +7 -0
  50. package/src/FullImageSegmentationAnnotator/index.story.js +177 -0
  51. package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
  52. package/src/GroupSelectorSidebarBox/index.js +48 -0
  53. package/src/GroupsEditorSidebarBox/index.js +108 -0
  54. package/src/HelpSidebarBox/index.js +43 -0
  55. package/src/HighlightBox/index.js +143 -0
  56. package/src/HistorySidebarBox/index.js +78 -0
  57. package/src/ImageCanvas/dancing-man.story.jpg +0 -0
  58. package/src/ImageCanvas/index.js +515 -0
  59. package/src/ImageCanvas/index.story.js +314 -0
  60. package/src/ImageCanvas/mouse_mask.story.png +0 -0
  61. package/src/ImageCanvas/region-tools.js +171 -0
  62. package/src/ImageCanvas/seves_desk.story.jpg +0 -0
  63. package/{ImageCanvas → src/ImageCanvas}/styles.js +8 -12
  64. package/src/ImageCanvas/use-mouse.js +168 -0
  65. package/src/ImageCanvas/use-project-box.js +23 -0
  66. package/src/ImageCanvas/use-wasd-mode.js +50 -0
  67. package/src/ImageMask/index.js +127 -0
  68. package/src/ImageMask/load-image.js +32 -0
  69. package/src/ImageSelectorSidebarBox/index.js +54 -0
  70. package/src/KeyframeTimeline/get-time-string.js +25 -0
  71. package/src/KeyframeTimeline/index.js +223 -0
  72. package/src/KeyframesSelectorSidebarBox/index.js +93 -0
  73. package/src/LandingPage/content.md +57 -0
  74. package/src/LandingPage/github-markdown.css +964 -0
  75. package/src/LandingPage/index.js +147 -0
  76. package/src/Locker/index.js +13 -0
  77. package/src/MainLayout/RightSidebarItemsWrapper.js +21 -0
  78. package/src/MainLayout/icon-dictionary.js +79 -0
  79. package/src/MainLayout/index.js +564 -0
  80. package/src/MainLayout/index.story.js +240 -0
  81. package/{MainLayout → src/MainLayout}/styles.js +7 -6
  82. package/src/MainLayout/types.js +171 -0
  83. package/src/MainLayout/use-implied-video-regions.js +17 -0
  84. package/src/MetadataEditorSidebarBox/index.js +160 -0
  85. package/src/PageSelector/index.js +159 -0
  86. package/src/PointDistances/index.js +90 -0
  87. package/src/PreventScrollToParents/index.js +48 -0
  88. package/src/PreventScrollToParents/index.story.js +23 -0
  89. package/src/RegionLabel/index.js +236 -0
  90. package/{RegionLabel → src/RegionLabel}/styles.js +15 -12
  91. package/src/RegionSelectAndTransformBoxes/index.js +236 -0
  92. package/src/RegionSelectorSidebarBox/index.js +220 -0
  93. package/{RegionSelectorSidebarBox → src/RegionSelectorSidebarBox}/styles.js +14 -13
  94. package/src/RegionShapes/index.js +254 -0
  95. package/src/RegionTags/index.js +136 -0
  96. package/src/SettingsDialog/index.js +58 -0
  97. package/src/SettingsProvider/index.js +57 -0
  98. package/src/Shortcuts/ShortcutField.js +44 -0
  99. package/src/Shortcuts/index.js +129 -0
  100. package/src/ShortcutsManager/index.js +162 -0
  101. package/src/Sidebar/index.js +117 -0
  102. package/src/SidebarBoxContainer/index.js +93 -0
  103. package/src/SmallToolButton/index.js +57 -0
  104. package/src/TagsSidebarBox/index.js +93 -0
  105. package/src/TaskDescriptionSidebarBox/index.js +43 -0
  106. package/src/Theme/index.js +36 -0
  107. package/src/VideoOrImageCanvasBackground/index.js +170 -0
  108. package/src/colors.js +32 -0
  109. package/src/hooks/use-colors.js +95 -0
  110. package/src/hooks/use-event-callback.js +11 -0
  111. package/src/hooks/use-exclude-pattern.js +27 -0
  112. package/src/hooks/use-load-image.js +21 -0
  113. package/src/hooks/use-window-size.js +46 -0
  114. package/{hooks → src/hooks}/xpattern.js +1 -1
  115. package/src/hooks/xpattern.png +0 -0
  116. package/src/index.js +18 -0
  117. package/src/lib.js +7 -0
  118. package/src/screenshot.png +0 -0
  119. package/src/site.css +5 -0
  120. package/src/stories.js +2 -0
  121. package/src/utils/blocks-to-article.js +61 -0
  122. package/{utils → src/utils}/blocks-to-article.test.js +8 -5
  123. package/{utils → src/utils}/default-locked-until.js +1 -2
  124. package/{utils → src/utils}/filter-only-unique.js +1 -1
  125. package/src/utils/get-from-local-storage.js +7 -0
  126. package/src/utils/get-hotkey-help-text.js +11 -0
  127. package/src/utils/get-landmarks-with-transform.js +23 -0
  128. package/src/utils/photosToImages.js +67 -0
  129. package/src/utils/regions-groups.js +19 -0
  130. package/src/utils/regions-to-blocks.js +16 -0
  131. package/src/utils/saveable-actions-enum.js +5 -0
  132. package/src/utils/set-in-local-storage.js +6 -0
  133. package/src/utils/sleep.js +3 -0
  134. package/src/utils/uuid-to-hash.js +5 -0
  135. package/Annotator/exampleImages.js +0 -41
  136. package/Annotator/examplePhotos.js +0 -6980
  137. package/Annotator/index.js +0 -417
  138. package/Annotator/reducers/combine-reducers.js +0 -14
  139. package/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -73
  140. package/Annotator/reducers/general-reducer.js +0 -1430
  141. package/Annotator/reducers/get-active-image.js +0 -27
  142. package/Annotator/reducers/get-implied-video-regions.js +0 -180
  143. package/Annotator/reducers/history-handler.js +0 -38
  144. package/Annotator/reducers/image-reducer.js +0 -20
  145. package/Annotator/reducers/video-reducer.js +0 -88
  146. package/ClassSelectionMenu/index.js +0 -140
  147. package/Crosshairs/index.js +0 -53
  148. package/DebugSidebarBox/index.js +0 -20
  149. package/DemoSite/Editor.js +0 -194
  150. package/DemoSite/ErrorBoundaryDialog.js +0 -64
  151. package/DemoSite/index.js +0 -40
  152. package/Editor/annotation-plugin/annotation.js +0 -647
  153. package/Editor/index.js +0 -93
  154. package/Editor/readOnly.js +0 -73
  155. package/Errorer/index.js +0 -11
  156. package/FullImageSegmentationAnnotator/index.js +0 -7
  157. package/GroupSelectorSidebarBox/index.js +0 -63
  158. package/GroupsEditorSidebarBox/index.js +0 -138
  159. package/HelpSidebarBox/index.js +0 -58
  160. package/HighlightBox/index.js +0 -102
  161. package/HistorySidebarBox/index.js +0 -71
  162. package/ImageCanvas/index.js +0 -441
  163. package/ImageCanvas/region-tools.js +0 -165
  164. package/ImageCanvas/use-mouse.js +0 -180
  165. package/ImageCanvas/use-project-box.js +0 -27
  166. package/ImageCanvas/use-wasd-mode.js +0 -62
  167. package/ImageMask/index.js +0 -133
  168. package/ImageMask/load-image.js +0 -25
  169. package/ImageSelectorSidebarBox/index.js +0 -60
  170. package/KeyframeTimeline/get-time-string.js +0 -27
  171. package/KeyframeTimeline/index.js +0 -233
  172. package/KeyframesSelectorSidebarBox/index.js +0 -93
  173. package/LandingPage/index.js +0 -159
  174. package/Locker/index.js +0 -11
  175. package/MainLayout/RightSidebarItemsWrapper.js +0 -19
  176. package/MainLayout/icon-dictionary.js +0 -104
  177. package/MainLayout/index.js +0 -526
  178. package/MainLayout/types.js +0 -0
  179. package/MainLayout/use-implied-video-regions.js +0 -13
  180. package/MetadataEditorSidebarBox/index.js +0 -231
  181. package/PageSelector/index.js +0 -180
  182. package/PointDistances/index.js +0 -73
  183. package/PreventScrollToParents/index.js +0 -51
  184. package/RegionLabel/index.js +0 -232
  185. package/RegionSelectAndTransformBoxes/index.js +0 -169
  186. package/RegionSelectorSidebarBox/index.js +0 -254
  187. package/RegionShapes/index.js +0 -294
  188. package/RegionTags/index.js +0 -144
  189. package/SettingsDialog/index.js +0 -52
  190. package/SettingsProvider/index.js +0 -60
  191. package/Shortcuts/ShortcutField.js +0 -46
  192. package/Shortcuts/index.js +0 -133
  193. package/ShortcutsManager/index.js +0 -155
  194. package/Sidebar/index.js +0 -69
  195. package/SidebarBoxContainer/index.js +0 -93
  196. package/SmallToolButton/index.js +0 -42
  197. package/TagsSidebarBox/index.js +0 -105
  198. package/TaskDescriptionSidebarBox/index.js +0 -58
  199. package/Theme/index.js +0 -30
  200. package/VideoOrImageCanvasBackground/index.js +0 -151
  201. package/colors.js +0 -14
  202. package/hooks/use-colors.js +0 -97
  203. package/hooks/use-event-callback.js +0 -10
  204. package/hooks/use-exclude-pattern.js +0 -24
  205. package/hooks/use-load-image.js +0 -26
  206. package/hooks/use-window-size.js +0 -46
  207. package/index.js +0 -3
  208. package/lib.js +0 -3
  209. package/stories.js +0 -5
  210. package/utils/blocks-to-article.js +0 -60
  211. package/utils/get-from-local-storage.js +0 -7
  212. package/utils/get-hotkey-help-text.js +0 -9
  213. package/utils/get-landmarks-with-transform.js +0 -40
  214. package/utils/photosToImages.js +0 -85
  215. package/utils/regions-groups.js +0 -28
  216. package/utils/regions-to-blocks.js +0 -18
  217. package/utils/saveable-actions-enum.js +0 -3
  218. package/utils/set-in-local-storage.js +0 -3
  219. package/utils/sleep.js +0 -7
  220. package/utils/uuid-to-hash.js +0 -5
  221. /package/{Errorer → src/Errorer}/errorer.css +0 -0
  222. /package/{Locker → src/Locker}/locker.css +0 -0
  223. /package/{PageSelector → src/PageSelector}/page-selector.css +0 -0
  224. /package/{utils → src/utils}/next-group-id.js +0 -0
@@ -0,0 +1,314 @@
1
+ import React from "react"
2
+
3
+ import { storiesOf } from "@storybook/react"
4
+ import { action } from "@storybook/addon-actions"
5
+
6
+ import ImageCanvas from "./"
7
+ import exampleMask from "./mouse_mask.story.png"
8
+ import exampleImage from "./seves_desk.story.jpg"
9
+ import dancingManImage from "./dancing-man.story.jpg"
10
+
11
+ export const testRegions = [
12
+ {
13
+ type: "point",
14
+ id: "point1",
15
+ cls: "Paper",
16
+ highlighted: true,
17
+ x: 0.8,
18
+ y: 0.5,
19
+ visible: true,
20
+ color: "#f00",
21
+ },
22
+ {
23
+ type: "point",
24
+ id: "point2",
25
+ cls: "Dude's Head",
26
+ tags: ["human", "head", "male"],
27
+ x: 0.1,
28
+ y: 0.15,
29
+ visible: true,
30
+ color: "#0F0",
31
+ },
32
+ {
33
+ type: "box",
34
+ id: "box1",
35
+ cls: "Business Card",
36
+ highlighted: true,
37
+ x: 0.315,
38
+ y: 0.63,
39
+ w: 0.067,
40
+ h: 0.045,
41
+ visible: true,
42
+ color: "#ff0",
43
+ },
44
+ {
45
+ type: "polygon",
46
+ id: "polygon1",
47
+ cls: "Laptop",
48
+ tags: ["Electronic Device"],
49
+ editingLabels: true,
50
+ highlighted: true,
51
+ points: [
52
+ [0.4019, 0.5065],
53
+ [0.407, 0.5895],
54
+ [0.4157, 0.6801],
55
+ [0.6579, 0.656],
56
+ [0.6115, 0.5674],
57
+ [0.5792, 0.4895],
58
+ ],
59
+ visible: true,
60
+ color: "#f0f",
61
+ },
62
+ {
63
+ type: "polygon",
64
+ id: "polygon2",
65
+ open: true,
66
+ points: [
67
+ [0.1201, 0.5987],
68
+ [0.0674, 0.7063],
69
+ [0.0726, 0.7477],
70
+ [0.2132, 0.7311],
71
+ ],
72
+ visible: true,
73
+ color: "#00f",
74
+ },
75
+ {
76
+ type: "pixel",
77
+ id: "pixel1",
78
+ cls: "Mouse",
79
+ tags: ["Electronic Device"],
80
+ sx: 0.7433,
81
+ sy: 0.5847,
82
+ w: 0.83 - 0.7433,
83
+ h: 0.67 - 0.5847,
84
+ src: exampleMask,
85
+ visible: true,
86
+ color: "#00f",
87
+ },
88
+ ]
89
+
90
+ export const testRegionsBoxes = [
91
+ {
92
+ type: "box",
93
+ id: "box1",
94
+ cls: "title",
95
+ highlighted: false,
96
+ groupHighlighted: false,
97
+ x: 0.315,
98
+ y: 0.63,
99
+ w: 0.067,
100
+ h: 0.045,
101
+ visible: true,
102
+ color: "#ff4133",
103
+ groupColor: "#2436ff",
104
+ groupId: "alpha",
105
+ text: "first box text"
106
+ },
107
+ {
108
+ type: "box",
109
+ id: "box2",
110
+ cls: "text",
111
+ highlighted: false,
112
+ groupHighlighted: false,
113
+ x: 0.415,
114
+ y: 0.63,
115
+ w: 0.067,
116
+ h: 0.045,
117
+ visible: true,
118
+ color: "#ff9924",
119
+ groupColor: "#2436ff",
120
+ groupId: "alpha",
121
+ text: "second box text"
122
+ },
123
+ {
124
+ type: "box",
125
+ id: "boxBeta1",
126
+ cls: "title",
127
+ highlighted: false,
128
+ groupHighlighted: false,
129
+ x: 0.315,
130
+ y: 0.43,
131
+ w: 0.067,
132
+ h: 0.045,
133
+ visible: true,
134
+ color: "#ff4133",
135
+ groupColor: "#78ffa7",
136
+ groupId: "beta",
137
+ text: "third box text"
138
+ },
139
+ {
140
+ type: "box",
141
+ id: "boxBeta2",
142
+ cls: "subtitle",
143
+ highlighted: false,
144
+ groupHighlighted: false,
145
+ x: 0.415,
146
+ y: 0.43,
147
+ w: 0.067,
148
+ h: 0.045,
149
+ visible: true,
150
+ color: "#ff9924",
151
+ groupColor: "#78ffa7",
152
+ groupId: "beta",
153
+ text: "fourth box text"
154
+ },
155
+ {
156
+ type: "box",
157
+ id: "boxBeta3",
158
+ cls: "text",
159
+ highlighted: false,
160
+ groupHighlighted: false,
161
+ x: 0.415,
162
+ y: 0.53,
163
+ w: 0.067,
164
+ h: 0.045,
165
+ visible: true,
166
+ color: "#007efc",
167
+ groupColor: "#78ffa7",
168
+ groupId: "beta",
169
+ text: "fifth box text"
170
+ },
171
+ {
172
+ type: "box",
173
+ id: "boxBeta4",
174
+ cls: "text",
175
+ highlighted: false,
176
+ groupHighlighted: false,
177
+ x: 0.415,
178
+ y: 0.73,
179
+ w: 0.067,
180
+ h: 0.045,
181
+ visible: true,
182
+ color: "#007efc",
183
+ groupColor: "#78ffa7",
184
+ groupId: "beta",
185
+ text: "sixth box text"
186
+ },
187
+
188
+ ]
189
+
190
+ const events = {
191
+ // Ignore common mouse movements, they fill the action log
192
+ onMouseMove: () => null, //action("onMouseMove"),
193
+ onMouseDown: () => null, //action("onMouseDown"),
194
+ onMouseUp: () => null, //action("onMouseUp"),
195
+
196
+ onChangeRegion: action("onChangeRegion"),
197
+ onBeginRegionEdit: action("onBeginRegionEdit"),
198
+ onCloseRegionEdit: action("onCloseRegionEdit"),
199
+
200
+ onSelectRegion: action("onSelectRegion"),
201
+
202
+ onBeginBoxTransform: action("onBeginBoxTransform"),
203
+
204
+ onBeginMovePolygonPoint: action("onBeginMovePolygonPoint"),
205
+ onAddPolygonPoint: action("onAddPolygonPoint"),
206
+ onClosePolygon: action("onClosePolygon"),
207
+
208
+ onBeginMoveKeypoint: action("onBeginMoveKeypoint"),
209
+
210
+ onBeginMovePoint: action("onBeginMovePoint"),
211
+ onDeleteRegion: action("onDeleteRegion"),
212
+ }
213
+
214
+ storiesOf("ImageCanvas", module)
215
+ .add("Basic", () => (
216
+ <ImageCanvas
217
+ regions={testRegions}
218
+ imageSrc={exampleImage}
219
+ showTags
220
+ {...events}
221
+ />
222
+ ))
223
+ .add("Zoom Tool Selected", () => (
224
+ <ImageCanvas
225
+ showTags
226
+ regions={testRegions}
227
+ imageSrc={exampleImage}
228
+ zoomWithPrimary
229
+ {...events}
230
+ />
231
+ ))
232
+ .add("Allowed Area", () => (
233
+ <ImageCanvas
234
+ showTags
235
+ regions={[]}
236
+ imageSrc={exampleImage}
237
+ zoomWithPrimary
238
+ allowedArea={{ x: 0.25, y: 0.25, w: 0.5, h: 0.5 }}
239
+ {...events}
240
+ />
241
+ ))
242
+ .add("Allowed Area (2)", () => (
243
+ <ImageCanvas
244
+ showTags
245
+ regions={[]}
246
+ imageSrc={exampleImage}
247
+ zoomWithPrimary
248
+ allowedArea={{ x: 0.6, y: 0.6, w: 0.2, h: 0.2 }}
249
+ {...events}
250
+ />
251
+ ))
252
+ .add("Modify Allowed Area", () => (
253
+ <ImageCanvas
254
+ showTags
255
+ regions={[]}
256
+ imageSrc={exampleImage}
257
+ modifyingAllowedArea
258
+ allowedArea={{ x: 0.6, y: 0.6, w: 0.2, h: 0.2 }}
259
+ {...events}
260
+ />
261
+ ))
262
+ .add("Poses", () => (
263
+ <ImageCanvas
264
+ keypointDefinitions={{
265
+ human: {
266
+ connections: [
267
+ ["head", "sternum"],
268
+ ["sternum", "leftElbow"],
269
+ ["sternum", "rightElbow"],
270
+ ],
271
+ landmarks: {
272
+ head: {
273
+ label: "Head",
274
+ color: "#f00",
275
+ defaultPosition: [0, -0.05],
276
+ },
277
+ sternum: {
278
+ label: "Torso",
279
+ color: "#0f0",
280
+ defaultPosition: [0, 0],
281
+ },
282
+ leftElbow: {
283
+ label: "Left Elbow",
284
+ color: "#00f",
285
+ defaultPosition: [-0.05, 0],
286
+ },
287
+ rightElbow: {
288
+ label: "Right Elbow",
289
+ color: "#00f",
290
+ defaultPosition: [0.05, 0],
291
+ },
292
+ },
293
+ },
294
+ }}
295
+ regions={[
296
+ {
297
+ type: "keypoints",
298
+ id: "keypoints1",
299
+ keypointsDefinitionId: "human",
300
+ highlighted: true,
301
+ points: {
302
+ head: { x: 0.54, y: 0.2 },
303
+ sternum: { x: 0.57, y: 0.3 },
304
+ leftElbow: { x: 0.4, y: 0.39 },
305
+ rightElbow: { x: 0.7, y: 0.32 },
306
+ },
307
+ visible: true,
308
+ },
309
+ ]}
310
+ imageSrc={dancingManImage}
311
+ showTags
312
+ {...events}
313
+ />
314
+ ))
@@ -0,0 +1,171 @@
1
+ // @flow
2
+
3
+ export type BaseRegion = {
4
+ id: string | number,
5
+ cls?: string,
6
+ locked?: boolean,
7
+ visible?: boolean,
8
+ color: string,
9
+ editingLabels?: boolean,
10
+ highlighted?: boolean,
11
+ tags?: Array<string>,
12
+ }
13
+
14
+ export type Point = {|
15
+ ...$Exact<BaseRegion>,
16
+ type: "point",
17
+ x: number,
18
+ y: number,
19
+ |}
20
+
21
+ export type PixelRegion =
22
+ | {|
23
+ ...$Exact<BaseRegion>,
24
+ type: "pixel",
25
+ sx: number,
26
+ sy: number,
27
+ w: number,
28
+ h: number,
29
+ src: string,
30
+ |}
31
+ | {|
32
+ ...$Exact<BaseRegion>,
33
+ type: "pixel",
34
+ points: Array<[number, number]>,
35
+ |}
36
+ export type Box = {|
37
+ ...$Exact<BaseRegion>,
38
+ type: "box",
39
+ x: number,
40
+ y: number,
41
+ w: number,
42
+ h: number,
43
+ |}
44
+
45
+ export type Polygon = {|
46
+ ...$Exact<BaseRegion>,
47
+ type: "polygon",
48
+ open?: boolean,
49
+ points: Array<[number, number]>,
50
+ |}
51
+
52
+ export type Line = {|
53
+ ...$Exact<BaseRegion>,
54
+ type: "line",
55
+ x1: number,
56
+ y1: number,
57
+ x2: number,
58
+ y2: number,
59
+ |}
60
+
61
+ export type ExpandingLine = {|
62
+ ...$Exact<BaseRegion>,
63
+ type: "expanding-line",
64
+ points: Array<{ x: number, y: number, angle: number, width: number }>,
65
+ |}
66
+
67
+ export type KeypointDefinition = {|
68
+ label: string,
69
+ color: string,
70
+ defaultPosition: [number, number],
71
+ |}
72
+
73
+ export type KeypointId = string
74
+
75
+ export type KeypointsDefinition = {|
76
+ [id: string]: {
77
+ connections: Array<[KeypointId, KeypointId]>,
78
+ landmarks: {
79
+ [KeypointId]: KeypointDefinition,
80
+ },
81
+ },
82
+ |}
83
+
84
+ export type Keypoints = {|
85
+ ...$Exact<BaseRegion>,
86
+ type: "keypoints",
87
+ keypointsDefinitionId: string,
88
+ points: {
89
+ [string]: { x: number, y: number },
90
+ },
91
+ |}
92
+
93
+ export type Region =
94
+ | Point
95
+ | PixelRegion
96
+ | Box
97
+ | Polygon
98
+ | ExpandingLine
99
+ | Keypoints
100
+
101
+ export const getEnclosingBox = (region: Region) => {
102
+ switch (region.type) {
103
+ case "polygon": {
104
+ const box = {
105
+ x: Math.min(...region.points.map(([x, y]) => x)),
106
+ y: Math.min(...region.points.map(([x, y]) => y)),
107
+ w: 0,
108
+ h: 0,
109
+ }
110
+ box.w = Math.max(...region.points.map(([x, y]) => x)) - box.x
111
+ box.h = Math.max(...region.points.map(([x, y]) => y)) - box.y
112
+ return box
113
+ }
114
+ case "keypoints": {
115
+ const minX = Math.min(
116
+ ...Object.values(region.points).map(({ x, y }) => x)
117
+ )
118
+ const minY = Math.min(
119
+ ...Object.values(region.points).map(({ x, y }) => y)
120
+ )
121
+ const maxX = Math.max(
122
+ ...Object.values(region.points).map(({ x, y }) => x)
123
+ )
124
+ const maxY = Math.max(
125
+ ...Object.values(region.points).map(({ x, y }) => y)
126
+ )
127
+ return {
128
+ x: minX,
129
+ y: minY,
130
+ w: maxX - minX,
131
+ h: maxY - minY,
132
+ }
133
+ }
134
+ case "expanding-line": {
135
+ const box = {
136
+ x: Math.min(...region.points.map(({ x, y }) => x)),
137
+ y: Math.min(...region.points.map(({ x, y }) => y)),
138
+ w: 0,
139
+ h: 0,
140
+ }
141
+ box.w = Math.max(...region.points.map(({ x, y }) => x)) - box.x
142
+ box.h = Math.max(...region.points.map(({ x, y }) => y)) - box.y
143
+ return box
144
+ }
145
+ case "line": {
146
+ return { x: region.x1, y: region.y1, w: 0, h: 0 }
147
+ }
148
+ case "box": {
149
+ return { x: region.x, y: region.y, w: region.w, h: region.h }
150
+ }
151
+ case "point": {
152
+ return { x: region.x, y: region.y, w: 0, h: 0 }
153
+ }
154
+ default: {
155
+ return { x: 0, y: 0, w: 0, h: 0 }
156
+ }
157
+ }
158
+ throw new Error("unknown region")
159
+ }
160
+
161
+ export const moveRegion = (region: Region, x: number, y: number) => {
162
+ switch (region.type) {
163
+ case "point": {
164
+ return { ...region, x, y }
165
+ }
166
+ case "box": {
167
+ return { ...region, x: x - region.w / 2, y: y - region.h / 2 }
168
+ }
169
+ }
170
+ return region
171
+ }
@@ -1,11 +1,7 @@
1
- import { grey } from "@mui/material/colors";
1
+ import { grey } from "@mui/material/colors"
2
+
2
3
  export default {
3
- canvas: {
4
- width: "100%",
5
- height: "100%",
6
- position: "relative",
7
- zIndex: 1
8
- },
4
+ canvas: { width: "100%", height: "100%", position: "relative", zIndex: 1 },
9
5
  zoomIndicator: {
10
6
  position: "absolute",
11
7
  bottom: 16,
@@ -15,7 +11,7 @@ export default {
15
11
  opacity: 0.5,
16
12
  fontWeight: "bolder",
17
13
  fontSize: 14,
18
- padding: 4
14
+ padding: 4,
19
15
  },
20
16
  fixedRegionLabel: {
21
17
  position: "absolute",
@@ -25,7 +21,7 @@ export default {
25
21
  opacity: 0.5,
26
22
  transition: "opacity 500ms",
27
23
  "&:hover": {
28
- opacity: 1
29
- }
30
- }
31
- };
24
+ opacity: 1,
25
+ },
26
+ },
27
+ }
@@ -0,0 +1,168 @@
1
+ // @flow weak
2
+
3
+ import { useRef } from "react"
4
+ import { Matrix } from "transformation-matrix-js"
5
+
6
+ const getDefaultMat = () => Matrix.from(1, 0, 0, 1, -10, -10)
7
+
8
+ export default ({
9
+ canvasEl,
10
+ changeMat,
11
+ changeDragging,
12
+ zoomStart,
13
+ zoomEnd,
14
+ changeZoomStart,
15
+ changeZoomEnd,
16
+ layoutParams,
17
+ zoomWithPrimary,
18
+ dragWithPrimary,
19
+ mat,
20
+ onMouseMove,
21
+ onMouseUp,
22
+ onMouseDown,
23
+ dragging,
24
+ }) => {
25
+ const mousePosition = useRef({ x: 0, y: 0 })
26
+ const prevMousePosition = useRef({ x: 0, y: 0 })
27
+
28
+ const zoomIn = (direction, point) => {
29
+ const [mx, my] = [point.x, point.y]
30
+ let scale =
31
+ typeof direction === "object" ? direction.to / mat.a : 1 + 0.2 * direction
32
+
33
+ // NOTE: We're mutating mat here
34
+ mat.translate(mx, my).scaleU(scale)
35
+ if (mat.a > 2) mat.scaleU(2 / mat.a)
36
+ if (mat.a < 0.05) mat.scaleU(0.05 / mat.a)
37
+ mat.translate(-mx, -my)
38
+
39
+ changeMat(mat.clone())
40
+ }
41
+
42
+ const mouseEvents = {
43
+ onMouseMove: (e) => {
44
+ const { left, top } = canvasEl.current.getBoundingClientRect()
45
+ prevMousePosition.current.x = mousePosition.current.x
46
+ prevMousePosition.current.y = mousePosition.current.y
47
+ mousePosition.current.x = e.clientX - left
48
+ mousePosition.current.y = e.clientY - top
49
+
50
+ const projMouse = mat.applyToPoint(
51
+ mousePosition.current.x,
52
+ mousePosition.current.y
53
+ )
54
+
55
+ if (zoomWithPrimary && zoomStart) {
56
+ changeZoomEnd(projMouse)
57
+ }
58
+
59
+ const { iw, ih } = layoutParams.current
60
+ onMouseMove({ x: projMouse.x / iw, y: projMouse.y / ih })
61
+
62
+ if (dragging) {
63
+ mat.translate(
64
+ prevMousePosition.current.x - mousePosition.current.x,
65
+ prevMousePosition.current.y - mousePosition.current.y
66
+ )
67
+
68
+ changeMat(mat.clone())
69
+ }
70
+ e.preventDefault()
71
+ },
72
+ onMouseDown: (e, specialEvent = {}) => {
73
+ e.preventDefault()
74
+
75
+ if (
76
+ e.button === 1 ||
77
+ e.button === 2 ||
78
+ (e.button === 0 && dragWithPrimary)
79
+ )
80
+ return changeDragging(true)
81
+
82
+ const projMouse = mat.applyToPoint(
83
+ mousePosition.current.x,
84
+ mousePosition.current.y
85
+ )
86
+ if (zoomWithPrimary && e.button === 0) {
87
+ changeZoomStart(projMouse)
88
+ changeZoomEnd(projMouse)
89
+ return
90
+ }
91
+ if (e.button === 0) {
92
+ if (specialEvent.type === "resize-box") {
93
+ // onResizeBox()
94
+ }
95
+ if (specialEvent.type === "move-region") {
96
+ // onResizeBox()
97
+ }
98
+ const { iw, ih } = layoutParams.current
99
+ onMouseDown({ x: projMouse.x / iw, y: projMouse.y / ih })
100
+ }
101
+ },
102
+ onMouseUp: (e) => {
103
+ e.preventDefault()
104
+ const projMouse = mat.applyToPoint(
105
+ mousePosition.current.x,
106
+ mousePosition.current.y
107
+ )
108
+ if (zoomStart) {
109
+ const zoomEnd = projMouse
110
+ if (
111
+ Math.abs(zoomStart.x - zoomEnd.x) < 10 &&
112
+ Math.abs(zoomStart.y - zoomEnd.y) < 10
113
+ ) {
114
+ if (mat.a < 1) {
115
+ zoomIn({ to: 1 }, mousePosition.current)
116
+ } else {
117
+ zoomIn({ to: 0.25 }, mousePosition.current)
118
+ }
119
+ } else {
120
+ const { iw, ih } = layoutParams.current
121
+
122
+ if (zoomStart.x > zoomEnd.x) {
123
+ ;[zoomStart.x, zoomEnd.x] = [zoomEnd.x, zoomStart.x]
124
+ }
125
+ if (zoomStart.y > zoomEnd.y) {
126
+ ;[zoomStart.y, zoomEnd.y] = [zoomEnd.y, zoomStart.y]
127
+ }
128
+
129
+ // The region defined by zoomStart and zoomEnd should be the new transform
130
+ let scale = Math.min(
131
+ (zoomEnd.x - zoomStart.x) / iw,
132
+ (zoomEnd.y - zoomStart.y) / ih
133
+ )
134
+ if (scale < 0.05) scale = 0.05
135
+ if (scale > 10) scale = 10
136
+
137
+ const newMat = getDefaultMat()
138
+ .translate(zoomStart.x, zoomStart.y)
139
+ .scaleU(scale)
140
+
141
+ changeMat(newMat.clone())
142
+ }
143
+
144
+ changeZoomStart(null)
145
+ changeZoomEnd(null)
146
+ }
147
+ if (
148
+ e.button === 1 ||
149
+ e.button === 2 ||
150
+ (e.button === 0 && dragWithPrimary)
151
+ )
152
+ return changeDragging(false)
153
+ if (e.button === 0) {
154
+ const { iw, ih } = layoutParams.current
155
+ onMouseUp({ x: projMouse.x / iw, y: projMouse.y / ih })
156
+ }
157
+ },
158
+ onWheel: (e) => {
159
+ const direction = e.deltaY > 0 ? 1 : e.deltaY < 0 ? -1 : 0
160
+ zoomIn(direction, mousePosition.current)
161
+ // e.preventDefault()
162
+ },
163
+ onContextMenu: (e) => {
164
+ e.preventDefault()
165
+ },
166
+ }
167
+ return { mouseEvents, mousePosition }
168
+ }
@@ -0,0 +1,23 @@
1
+ // @flow weak
2
+ import useEventCallback from "use-event-callback"
3
+ import { getEnclosingBox } from "./region-tools.js"
4
+
5
+ export default ({ layoutParams, mat }) => {
6
+ return useEventCallback((r) => {
7
+ const { iw, ih } = layoutParams.current
8
+ const bbox = getEnclosingBox(r)
9
+ const margin = r.type === "point" ? 15 : 2
10
+ const cbox = {
11
+ x: bbox.x * iw - margin,
12
+ y: bbox.y * ih - margin,
13
+ w: bbox.w * iw + margin * 2,
14
+ h: bbox.h * ih + margin * 2,
15
+ }
16
+ const pbox = {
17
+ ...mat.clone().inverse().applyToPoint(cbox.x, cbox.y),
18
+ w: cbox.w / mat.a,
19
+ h: cbox.h / mat.d,
20
+ }
21
+ return pbox
22
+ })
23
+ }