2
2
* #%L
3
3
* Image Crop Add-on
4
4
* %%
5
- * Copyright (C) 2024 Flowing Code
5
+ * Copyright (C) 2024-2025 Flowing Code
6
6
* %%
7
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
8
* you may not use this file except in compliance with the License.
21
21
import { ReactAdapterElement , RenderHooks } from 'Frontend/generated/flow/ReactAdapter' ;
22
22
import { JSXElementConstructor , ReactElement , useRef , useEffect } from "react" ;
23
23
import React from 'react' ;
24
- import { type Crop , ReactCrop , PixelCrop , makeAspectCrop , centerCrop } from "react-image-crop" ;
24
+ import { type Crop , ReactCrop , PixelCrop , PercentCrop , makeAspectCrop , centerCrop , convertToPixelCrop } from "react-image-crop" ;
25
25
26
26
class ImageCropElement extends ReactAdapterElement {
27
27
@@ -70,6 +70,7 @@ class ImageCropElement extends ReactAdapterElement {
70
70
height
71
71
)
72
72
setCrop ( newcrop ) ;
73
+ this . _updateCroppedImage ( newcrop ) ;
73
74
}
74
75
}
75
76
} ;
@@ -122,69 +123,9 @@ class ImageCropElement extends ReactAdapterElement {
122
123
} ;
123
124
124
125
const onComplete = ( c : PixelCrop ) => {
125
- croppedImageEncode ( c ) ;
126
+ this . _updateCroppedImage ( c ) ;
126
127
} ;
127
-
128
- const croppedImageEncode = ( completedCrop : PixelCrop ) => {
129
- if ( completedCrop ) {
130
-
131
- // get the image element
132
- const image = imgRef . current ;
133
-
134
- // create a canvas element to draw the cropped image
135
- const canvas = document . createElement ( "canvas" ) ;
136
-
137
- // draw the image on the canvas
138
- if ( image ) {
139
- const ccrop = completedCrop ;
140
- const scaleX = image . naturalWidth / image . width ;
141
- const scaleY = image . naturalHeight / image . height ;
142
- const ctx = canvas . getContext ( "2d" ) ;
143
- const pixelRatio = window . devicePixelRatio ;
144
- canvas . width = ccrop . width * pixelRatio ;
145
- canvas . height = ccrop . height * pixelRatio ;
146
-
147
- if ( ctx ) {
148
- ctx . setTransform ( pixelRatio , 0 , 0 , pixelRatio , 0 , 0 ) ;
149
- ctx . imageSmoothingQuality = "high" ;
150
-
151
- ctx . save ( ) ;
152
-
153
- if ( circularCrop ) {
154
- canvas . width = ccrop . width ;
155
- canvas . height = ccrop . height ;
156
-
157
- ctx . beginPath ( ) ;
158
-
159
- ctx . arc ( ccrop . width / 2 , ccrop . height / 2 , ccrop . height / 2 , 0 , Math . PI * 2 , true ) ;
160
- ctx . closePath ( ) ;
161
- ctx . clip ( ) ;
162
- }
163
-
164
- ctx . drawImage (
165
- image ,
166
- ccrop . x * scaleX ,
167
- ccrop . y * scaleY ,
168
- ccrop . width * scaleX ,
169
- ccrop . height * scaleY ,
170
- 0 ,
171
- 0 ,
172
- ccrop . width ,
173
- ccrop . height
174
- ) ;
175
-
176
- ctx . restore ( ) ;
177
- }
178
-
179
- // get the cropped image
180
- let croppedImageDataUri = canvas . toDataURL ( "image/png" , 1.0 ) ;
181
-
182
- // dispatch the event containing cropped image
183
- this . fireCroppedImageEvent ( croppedImageDataUri ) ;
184
- }
185
- }
186
- }
187
-
128
+
188
129
return (
189
130
< ReactCrop
190
131
crop = { crop }
@@ -219,6 +160,61 @@ class ImageCropElement extends ReactAdapterElement {
219
160
} )
220
161
) ;
221
162
}
163
+
164
+ public _updateCroppedImage ( crop : PixelCrop | PercentCrop ) {
165
+ const image = this . querySelector ( "img" ) ;
166
+ if ( crop && image ) {
167
+
168
+ crop = convertToPixelCrop ( crop , image . width , image . height ) ;
169
+
170
+ // create a canvas element to draw the cropped image
171
+ const canvas = document . createElement ( "canvas" ) ;
172
+
173
+ // draw the image on the canvas
174
+ const ccrop = crop ;
175
+ const scaleX = image . naturalWidth / image . width ;
176
+ const scaleY = image . naturalHeight / image . height ;
177
+ const ctx = canvas . getContext ( "2d" ) ;
178
+ const pixelRatio = window . devicePixelRatio ;
179
+ canvas . width = ccrop . width * pixelRatio ;
180
+ canvas . height = ccrop . height * pixelRatio ;
181
+
182
+ if ( ctx ) {
183
+ ctx . setTransform ( pixelRatio , 0 , 0 , pixelRatio , 0 , 0 ) ;
184
+ ctx . imageSmoothingQuality = "high" ;
185
+ ctx . save ( ) ;
186
+
187
+ if ( this . circularCrop ) {
188
+ canvas . width = ccrop . width ;
189
+ canvas . height = ccrop . height ;
190
+ ctx . beginPath ( ) ;
191
+ ctx . arc ( ccrop . width / 2 , ccrop . height / 2 , ccrop . height / 2 , 0 , Math . PI * 2 , true ) ;
192
+ ctx . closePath ( ) ;
193
+ ctx . clip ( ) ;
194
+ }
195
+
196
+ ctx . drawImage (
197
+ image ,
198
+ ccrop . x * scaleX ,
199
+ ccrop . y * scaleY ,
200
+ ccrop . width * scaleX ,
201
+ ccrop . height * scaleY ,
202
+ 0 ,
203
+ 0 ,
204
+ ccrop . width ,
205
+ ccrop . height
206
+ ) ;
207
+
208
+ ctx . restore ( ) ;
209
+
210
+ // get the cropped image
211
+ let croppedImageDataUri = canvas . toDataURL ( "image/png" , 1.0 ) ;
212
+
213
+ // dispatch the event containing cropped image
214
+ this . fireCroppedImageEvent ( croppedImageDataUri ) ;
215
+ }
216
+ }
217
+ }
222
218
}
223
219
224
220
customElements . define ( "image-crop" , ImageCropElement ) ;
0 commit comments