Skip to content

Commit cec972c

Browse files
javier-godoypaodb
authored andcommitted
fix: update cropped image when crop is set from server side
Close #19
1 parent 6c920d2 commit cec972c

File tree

2 files changed

+62
-65
lines changed

2 files changed

+62
-65
lines changed

src/main/java/com/flowingcode/vaadin/addons/imagecrop/ImageCrop.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
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.
@@ -139,6 +139,7 @@ public String getImageAlt() {
139139
*/
140140
public void setCrop(Crop crop) {
141141
setState("crop", crop);
142+
getElement().executeJs("this._updateCroppedImage(this.crop)");
142143
}
143144

144145
/**

src/main/resources/META-INF/resources/frontend/src/image-crop.tsx

Lines changed: 60 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
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.
@@ -21,7 +21,7 @@
2121
import { ReactAdapterElement, RenderHooks } from 'Frontend/generated/flow/ReactAdapter';
2222
import { JSXElementConstructor, ReactElement, useRef, useEffect } from "react";
2323
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";
2525

2626
class 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

224220
customElements.define("image-crop", ImageCropElement);

0 commit comments

Comments
 (0)