pull/199/merge
Youxia 7 months ago committed by GitHub
commit cd56b2d6ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -10,6 +10,7 @@ interface ImagePickerProps extends PropsWithChildren {
className?: string;
imageUrl?: string; // 初始image url, 仅children为空时生效
aspect?: number;
maxSize?: number;
onChange?: (blobUrl: string) => void;
disabled?: boolean; // 禁用选择
}
@ -43,6 +44,7 @@ export const ImagePicker: React.FC<ImagePickerProps> = React.memo((props) => {
<ImageCropperModal
imageUrl={reader.result.toString()}
aspect={props.aspect}
maxSize={props.maxSize}
onConfirm={(croppedImageBlobUrl) => {
closeModal(key);
updateAvatar(croppedImageBlobUrl);

@ -12,6 +12,7 @@ import { ImagePicker } from './ImagePicker';
interface ImageUploaderProps extends PropsWithChildren {
circle?: boolean;
aspect?: number;
maxSize?: number;
className?: string;
usage?: UploadFileUsage;
onUploadSuccess: (fileInfo: UploadFileResult) => void;
@ -46,6 +47,7 @@ export const ImageUploader: React.FC<ImageUploaderProps> = React.memo(
'rounded-full': props.circle,
})}
aspect={aspect}
maxSize={props.maxSize}
disabled={loading}
onChange={handlePickImage}
>
@ -65,7 +67,14 @@ ImageUploader.displayName = 'ImageUploader';
export const AvatarUploader: React.FC<ImageUploaderProps> = React.memo(
(props) => {
return <ImageUploader aspect={1} circle={true} {...props}></ImageUploader>;
return (
<ImageUploader
aspect={1}
maxSize={256}
circle={true}
{...props}
></ImageUploader>
);
}
);
AvatarUploader.displayName = 'AvatarUploader';

@ -11,9 +11,11 @@ import { ModalWrapper } from '../Modal';
export const ImageCropperModal: React.FC<{
imageUrl: string;
aspect?: number;
maxSize?: number;
onConfirm: (croppedImageBlobUrl: string) => void;
}> = React.memo((props) => {
const aspect = props.aspect ?? 1;
const maxSize = props.maxSize ?? Infinity;
const [crop, setCrop] = useState({ x: 0, y: 0 });
const [zoom, setZoom] = useState(1);
const [area, setArea] = useState<Area>({ width: 0, height: 0, x: 0, y: 0 });
@ -21,7 +23,10 @@ export const ImageCropperModal: React.FC<{
const handleConfirm = async () => {
const blobUrl = await getCroppedImg(
await createImage(props.imageUrl),
area
area,
0,
'newFile.jpeg',
maxSize
);
props.onConfirm(blobUrl);
};
@ -73,48 +78,45 @@ let fileUrlTemp: string | null = null; // 缓存裁剪后的图片url
* @param crop
* @param rotation
* @param fileName
* @param maxSize
* @returns blob url
*/
function getCroppedImg(
image: HTMLImageElement,
crop: Area,
rotation = 0,
fileName = 'newFile.jpeg'
fileName = 'newFile.jpeg',
maxSize = Infinity
): Promise<string> {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (!_isNil(ctx)) {
const maxSize = Math.max(image.width, image.height);
const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2));
// 计算最大尺寸
const size = Math.min(Math.max(crop.width, crop.height), maxSize);
// set each dimensions to double largest dimension to allow for a safe area for the
// image to rotate in without being clipped by canvas context
canvas.width = safeArea;
canvas.height = safeArea;
// 计算缩放比例
const scale = size / Math.max(crop.width, crop.height);
canvas.width = scale * crop.width;
canvas.height = scale * crop.height;
// translate canvas context to a central location on image to allow rotating around the center.
ctx.translate(safeArea / 2, safeArea / 2);
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(getRadianAngle(rotation));
ctx.translate(-safeArea / 2, -safeArea / 2);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
// draw rotated image and store data.
ctx.drawImage(
image,
safeArea / 2 - image.width * 0.5,
safeArea / 2 - image.height * 0.5
);
const data = ctx.getImageData(0, 0, safeArea, safeArea);
// set canvas width to final desired crop size - this will clear existing context
canvas.width = crop.width;
canvas.height = crop.height;
// paste generated rotate image with correct offsets for x,y crop values.
ctx.putImageData(
data,
Math.round(0 - safeArea / 2 + image.width * 0.5 - crop.x),
Math.round(0 - safeArea / 2 + image.height * 0.5 - crop.y)
0,
0,
image.width,
image.height,
-crop.x * scale,
-crop.y * scale,
image.width * scale,
image.height * scale
);
}

Loading…
Cancel
Save