Skip to content

Commit 2b89c33

Browse files
author
ricwilson
committed
refactor: enhance useCropToBase64 with circular crop option and clean up code
1 parent 30c9a93 commit 2b89c33

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

ImageCrop/ImageCrop/components/imageCropControl.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ const ImageCropControl: React.FC<IImageCropControlProps> = (props) => {
6262
const scaling = useScaling(pcfContext.context);
6363

6464
// Use custom hook to handle crop-to-base64 conversion and callback
65-
useCropToBase64(imgRef, completedCrop, props.onCropComplete, rotation, scaling);
66-
67-
// Optionally, recenter crop when aspect changes (already handled in hook)
65+
useCropToBase64(imgRef, completedCrop, props.onCropComplete, rotation, scaling, circularCrop);
6866

6967
return (
7068
<CropWrapper

ImageCrop/ImageCrop/hooks/useAspect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function useAspect(
3030
useEffect(() => {
3131
const currentAspect = getAspect();
3232
setAspect(currentAspect);
33-
33+
3434
if (!currentAspect || currentAspect === 0) return;
3535

3636
if (imgRef?.current && setCrop) {

ImageCrop/ImageCrop/hooks/useCropToBase64.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export function useCropToBase64(
66
completedCrop: PixelCrop | undefined,
77
onCropComplete: (base64: string) => void,
88
rotation: number = 0,
9-
scaling: number = 1
9+
scaling: number = 1,
10+
circularCrop: boolean = false
1011
) {
1112
useEffect(() => {
1213
if (!completedCrop || !imgRef.current) return;
@@ -25,6 +26,22 @@ export function useCropToBase64(
2526
ctx.scale(pixelRatio, pixelRatio);
2627
ctx.imageSmoothingQuality = "high";
2728

29+
// Circular crop: set a circular clipping path
30+
if (circularCrop) {
31+
ctx.save();
32+
ctx.beginPath();
33+
const radius = Math.min(canvas.width, canvas.height) / (2 * pixelRatio);
34+
ctx.arc(
35+
canvas.width / (2 * pixelRatio),
36+
canvas.height / (2 * pixelRatio),
37+
radius,
38+
0,
39+
2 * Math.PI
40+
);
41+
ctx.closePath();
42+
ctx.clip();
43+
}
44+
2845
const cropX = completedCrop.x * scaleX;
2946
const cropY = completedCrop.y * scaleY;
3047
const rotateRads = (rotation * Math.PI) / 180;
@@ -51,6 +68,10 @@ export function useCropToBase64(
5168
);
5269
ctx.restore();
5370

71+
if (circularCrop) {
72+
ctx.restore(); // Restore after clipping
73+
}
74+
5475
canvas.toBlob(
5576
(blob) => {
5677
if (!blob) return;
@@ -64,5 +85,5 @@ export function useCropToBase64(
6485
},
6586
"image/png"
6687
);
67-
}, [completedCrop, imgRef, onCropComplete, rotation, scaling]);
88+
}, [completedCrop, imgRef, onCropComplete, rotation, scaling, circularCrop]);
6889
}

ImageCrop/ImageCrop/imageCropApp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from "react";
22
import { PcfContextProvider } from "./services/pcfContext";
3-
import { IPcfContextServiceProps, PcfContextService } from "./services/pcfContextService";
3+
import { PcfContextService } from "./services/pcfContextService";
44
import ImageCropControl from "./components/imageCropControl";
55
import { IImageCropControlProps } from "./types/imageCropTypes";
66

ImageCrop/ImageCrop/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export class ImageCrop implements ComponentFramework.StandardControl<IInputs, IO
5656
* @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
5757
*/
5858
public updateView(context: ComponentFramework.Context<IInputs>): void {
59-
if (this._updateFromOutput) {
60-
this._updateFromOutput = false;
61-
return;
62-
}
59+
// if (this._updateFromOutput) {
60+
// this._updateFromOutput = false;
61+
// return;
62+
// }
6363

6464
this._reactRoot.render(
6565
React.createElement(ImageCropApp, {

0 commit comments

Comments
 (0)