I am using canvas to capture the cropped image. here is the function
export const getCroppedImg = (
image: HTMLImageElement,
crop: Crop,
fileName: string
): Promise<Blob> => {
let canvas: HTMLCanvasElement;
let ctx: CanvasRenderingContext2D;
// I m using next.js
if (typeof window !== "undefined") {
if (crop) {
canvas = document.createElement("canvas");
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width =crop.width ? crop.width * scaleX : undefined;
canvas.height =crop.height && crop.height * scaleY;
ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width * scaleX,
crop.height * scaleY
);
}
}
crop.x, crop.y, crop.width crop.height
causing ts error "Object is possibly 'undefined' ". I wrapped entire logic with if(crop)
, i tried two diffent approaches
canvas.width =crop.width ? crop.width * scaleX : undefined;
canvas.height =crop.height && crop.height * scaleY;
"canvas.width" and "canvas.height" warns that
"Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.ts(2322)
Here is the Crop:
import { Crop } from "react-image-crop";
interface Crop {
aspect?: number;
x?: number;
y?: number;
width?: number;
height?: number;
unit?: 'px' | '%';
}
CodePudding user response:
Take out the existing crop.width
and crop.height
into their own variables before checking them.
You also can't assign undefined
to a canvas.width
, or use &&
to conditionally assign a value to the height - use if
instead.
It doesn't look like proceeding with any of the logic makes sense if any of the crop
properties are undefined (you wouldn't be able to draw the canvas or use drawImage
properly), so throw an error or return early in such cases.
You also aren't returning a Promise, so remove the Promise<Blob>
type.
export const getCroppedImg = (
image: HTMLImageElement,
crop: Crop,
) => {
const { width, height, x, y } = crop;
if (typeof window === "undefined" || !width || !height || !x || !y) {
// Proceeding further would make no sense;
// can't adjust canvas, or draw the image
// return here, or throw an error or something
throw new Error('Bad argument');
}
const canvas = document.createElement("canvas");
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = width * scaleX;
canvas.height = height * scaleY;
const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
ctx.drawImage(
image,
x * scaleX,
y * scaleY,
width * scaleX,
height * scaleY,
0,
0,
width * scaleX,
height * scaleY
);
}
CodePudding user response:
You are saying in this line that canvas.width could be undefined:
canvas.width =crop.width ? crop.width * scaleX : undefined;
so you can re work the logic so that is not the case. That being said, sometimes you will know more than the TypeScript compiler so if you know that the value will never be undefined when you need to access it, you can assert the value.
canvas.width as number
CodePudding user response:
Why do you use optional fields on Crop interface?
Have you tried this?:
interface Crop {
aspect: number;
x: number;
y: number;
width: number;
height: number;
unit: 'px' | '%';
}