22 * #%L
33 * Image Crop Add-on
44 * %%
5- * Copyright (C) 2024 Flowing Code
5+ * Copyright (C) 2024-2025 Flowing Code
66 * %%
77 * Licensed under the Apache License, Version 2.0 (the "License");
88 * you may not use this file except in compliance with the License.
2121import { ReactAdapterElement , RenderHooks } from 'Frontend/generated/flow/ReactAdapter' ;
2222import { JSXElementConstructor , ReactElement , useRef , useEffect } from "react" ;
2323import 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" ;
2525
2626class ImageCropElement extends ReactAdapterElement {
2727
@@ -70,6 +70,7 @@ class ImageCropElement extends ReactAdapterElement {
7070 height
7171 )
7272 setCrop ( newcrop ) ;
73+ this . _updateCroppedImage ( newcrop ) ;
7374 }
7475 }
7576 } ;
@@ -122,69 +123,9 @@ class ImageCropElement extends ReactAdapterElement {
122123 } ;
123124
124125 const onComplete = ( c : PixelCrop ) => {
125- croppedImageEncode ( c ) ;
126+ this . _updateCroppedImage ( c ) ;
126127 } ;
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+
188129 return (
189130 < ReactCrop
190131 crop = { crop }
@@ -219,6 +160,61 @@ class ImageCropElement extends ReactAdapterElement {
219160 } )
220161 ) ;
221162 }
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+ }
222218}
223219
224220customElements . define ( "image-crop" , ImageCropElement ) ;
0 commit comments