META-INF.resources.frontend.src.image-crop.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of image-crop-addon Show documentation
Show all versions of image-crop-addon Show documentation
Image Crop Add-on for Vaadin Flow
The newest version!
/*-
* #%L
* Image Crop Add-on
* %%
* Copyright (C) 2024 Flowing Code
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import { ReactAdapterElement, RenderHooks } from 'Frontend/generated/flow/ReactAdapter';
import { JSXElementConstructor, ReactElement, useRef } from "react";
import React from 'react';
import { type Crop, ReactCrop, PixelCrop, makeAspectCrop, centerCrop } from "react-image-crop";
class ImageCropElement extends ReactAdapterElement {
protected render(hooks: RenderHooks): ReactElement> | null {
const [crop, setCrop] = hooks.useState("crop");
const [imgSrc] = hooks.useState("imgSrc");
const imgRef = useRef(null);
const [imgAlt] = hooks.useState("imgAlt");
const [aspect] = hooks.useState("aspect");
const [circularCrop] = hooks.useState("circularCrop", false);
const [keepSelection] = hooks.useState("keepSelection", false);
const [disabled] = hooks.useState("disabled", false);
const [locked] = hooks.useState("locked", false);
const [minWidth] = hooks.useState("minWidth");
const [minHeight] = hooks.useState("minHeight");
const [maxWidth] = hooks.useState("maxWidth");
const [maxHeight] = hooks.useState("maxHeight");
const [ruleOfThirds] = hooks.useState("ruleOfThirds", false);
const onImageLoad = () => {
if (imgRef.current && crop) {
const { width, height } = imgRef.current;
const newcrop = centerCrop(
makeAspectCrop(
{
unit: crop.unit,
width: crop.width,
height: crop.height,
x: crop.x,
y: crop.y
},
aspect,
width,
height
),
width,
height
)
setCrop(newcrop);
}
};
const onChange = (c: Crop) => {
setCrop(c);
};
const onComplete = (c: PixelCrop) => {
croppedImageEncode(c);
};
const croppedImageEncode = (completedCrop: PixelCrop) => {
if (completedCrop) {
// get the image element
const image = imgRef.current;
// create a canvas element to draw the cropped image
const canvas = document.createElement("canvas");
// draw the image on the canvas
if (image) {
const ccrop = completedCrop;
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
const ctx = canvas.getContext("2d");
const pixelRatio = window.devicePixelRatio;
canvas.width = ccrop.width * pixelRatio * scaleX;
canvas.height = ccrop.height * pixelRatio * scaleY;
if (ctx) {
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.imageSmoothingQuality = "high";
ctx.save();
if (circularCrop) {
canvas.width = ccrop.width;
canvas.height = ccrop.height;
ctx.beginPath();
ctx.arc(ccrop.width / 2, ccrop.height / 2, ccrop.height / 2, 0, Math.PI * 2, true);
ctx.closePath();
ctx.clip();
}
ctx.drawImage(
image,
ccrop.x * scaleX,
ccrop.y * scaleY,
ccrop.width * scaleX,
ccrop.height * scaleY,
0,
0,
ccrop.width,
ccrop.height
);
ctx.restore();
}
// get the cropped image
let croppedImageDataUri = canvas.toDataURL("image/png", 1.0);
// dispatch the event containing cropped image
this.fireCroppedImageEvent(croppedImageDataUri);
}
}
}
return (
onChange(c)}
onComplete={(c: PixelCrop) => onComplete(c)}
circularCrop={circularCrop}
aspect={aspect}
keepSelection={keepSelection}
disabled={disabled}
locked={locked}
minWidth={minWidth}
minHeight={minHeight}
maxWidth={maxWidth}
maxHeight={maxHeight}
ruleOfThirds={ruleOfThirds}
>
);
}
private fireCroppedImageEvent(croppedImageDataUri: string) {
this.dispatchEvent(
new CustomEvent("cropped-image", {
detail: {
croppedImageDataUri: croppedImageDataUri
},
})
);
}
}
customElements.define("image-crop", ImageCropElement);
© 2015 - 2025 Weber Informatics LLC | Privacy Policy