使用 Canvas 缩放图像并等待结果
Scale Images using Canvas and wait for Result
我正在使用 react-dropzone 上传文件。
<Dropzone
accept="image/jpeg"
multiple
onDrop={(acceptedFiles, rejectedFiles) => this.onDrop(acceptedFiles, rejectedFiles)}
/>
在 onDrop 函数中,我缩放了使用 canvas 获得的每个图像。
onDrop(acceptedFiles: Array<Object>, rejectedFiles: Array<Object>) {
if (acceptedFiles.length) {
const requestParams = {
parameters: {
generateContourImages: false,
},
images: [],
};
acceptedFiles.forEach(async (acceptedFile) => {
const { width, height } = await browserImageSize(acceptedFile);
const imagedata = await this.scaleImage(acceptedFile, width, height);
requestParams.images.push({
imagedata,
methods: methods,
imageID: uuidv4(),
});
});
} else {
this.setState({ error: true });
}
}
实际缩放发生在下面的函数中
async scaleImage(fileImage: Object, originalWidth: number, originalHeight: number) {
return new Promise((resolve) => {
const imageURL = URL.createObjectURL(fileImage);
const image = new Image();
image.onload = () => {
const scaleFactor = Math.max(originalWidth, originalHeight) / 1000;
const canvas = document.createElement('canvas');
canvas.width = originalWidth;
canvas.height = originalHeight;
const scaledWidth = Math.floor(originalWidth / scaleFactor);
const scaledHeight = Math.floor(originalHeight / scaleFactor);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
const base64 = canvas.toDataURL('image/jpeg');
resolve(base64.substr(23));
}
image.src = imageURL;
});
}
然后我构造的requestParams
对象将被发送到服务器。我的问题是我希望我的客户端代码等到它遍历所有图像并构造最终的 requestParams
对象。现在不是这样了。如何让上面的代码等待?
可以通过以下方式实现:
async constructRequestParams(acceptedFiles: Array<Object>) {
return new Promise((resolve) => {
const requestParams = {
parameters: {
generateContourImages: false,
},
images: [],
};
acceptedFiles.forEach(async (acceptedFile, index) => {
const { width, height } = await browserImageSize(acceptedFile);
const imagedata = await this.scaleImage(acceptedFile, width, height);
requestParams.images.push({
imagedata,
methods: methods,
imageID: uuidv4(),
});
if (requestParams.images.length === acceptedFiles.length) {
resolve(requestParams);
}
});
})
}
async onDrop(acceptedFiles: Array<Object>, rejectedFiles: Array<Object>) {
if (acceptedFiles.length) {
const requestParams = await this.constructRequestParams(acceptedFiles);
} else {
this.setState({ error: true });
}
}
我正在使用 react-dropzone 上传文件。
<Dropzone
accept="image/jpeg"
multiple
onDrop={(acceptedFiles, rejectedFiles) => this.onDrop(acceptedFiles, rejectedFiles)}
/>
在 onDrop 函数中,我缩放了使用 canvas 获得的每个图像。
onDrop(acceptedFiles: Array<Object>, rejectedFiles: Array<Object>) {
if (acceptedFiles.length) {
const requestParams = {
parameters: {
generateContourImages: false,
},
images: [],
};
acceptedFiles.forEach(async (acceptedFile) => {
const { width, height } = await browserImageSize(acceptedFile);
const imagedata = await this.scaleImage(acceptedFile, width, height);
requestParams.images.push({
imagedata,
methods: methods,
imageID: uuidv4(),
});
});
} else {
this.setState({ error: true });
}
}
实际缩放发生在下面的函数中
async scaleImage(fileImage: Object, originalWidth: number, originalHeight: number) {
return new Promise((resolve) => {
const imageURL = URL.createObjectURL(fileImage);
const image = new Image();
image.onload = () => {
const scaleFactor = Math.max(originalWidth, originalHeight) / 1000;
const canvas = document.createElement('canvas');
canvas.width = originalWidth;
canvas.height = originalHeight;
const scaledWidth = Math.floor(originalWidth / scaleFactor);
const scaledHeight = Math.floor(originalHeight / scaleFactor);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
const base64 = canvas.toDataURL('image/jpeg');
resolve(base64.substr(23));
}
image.src = imageURL;
});
}
然后我构造的requestParams
对象将被发送到服务器。我的问题是我希望我的客户端代码等到它遍历所有图像并构造最终的 requestParams
对象。现在不是这样了。如何让上面的代码等待?
可以通过以下方式实现:
async constructRequestParams(acceptedFiles: Array<Object>) {
return new Promise((resolve) => {
const requestParams = {
parameters: {
generateContourImages: false,
},
images: [],
};
acceptedFiles.forEach(async (acceptedFile, index) => {
const { width, height } = await browserImageSize(acceptedFile);
const imagedata = await this.scaleImage(acceptedFile, width, height);
requestParams.images.push({
imagedata,
methods: methods,
imageID: uuidv4(),
});
if (requestParams.images.length === acceptedFiles.length) {
resolve(requestParams);
}
});
})
}
async onDrop(acceptedFiles: Array<Object>, rejectedFiles: Array<Object>) {
if (acceptedFiles.length) {
const requestParams = await this.constructRequestParams(acceptedFiles);
} else {
this.setState({ error: true });
}
}