useRef总是返回null,并且无法在图像比较中获得当前值



我正在尝试使用像素匹配库来比较两个图像的反应组件,我被困在输出图像上。outputCanvasRef总是null,所以在compareImages函数中,它在outputCanvas.width = image1.width;

一行出错。
import { useRef, useState } from "react";
import pixelmatch from "pixelmatch";
const Tab1 = () => {
const [image1, setImage1] = useState(null);
const [image2, setImage2] = useState(null);
const [difference, setDifference] = useState(null);
const canvas1Ref = useRef(null);
const canvas2Ref = useRef(null);
const outputCanvasRef = useRef(null);
const handleFileChange = (setImage) => (event) => {
const file = event.target.files[0];
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
const image = new Image();
image.src = fileReader.result;
image.onload = () => setImage(image);
};
};
const compareImages = async () => {
if (image1 && image2) {
const canvas1 = canvas1Ref.current;
const canvas2 = canvas2Ref.current;
const outputCanvas = outputCanvasRef.current;
canvas1.width = image1.width;
canvas1.height = image1.height;
canvas2.width = image2.width;
canvas2.height = image2.height;
outputCanvas.width = image1.width;
outputCanvas.height = image1.height;
const ctx1 = canvas1.getContext("2d");
const ctx2 = canvas2.getContext("2d");
const outputCtx = outputCanvas.getContext("2d");
outputCtx.scale(0.5, 0.5);
ctx1.drawImage(image1, 0, 0);
ctx2.drawImage(image2, 0, 0);
const diff = pixelmatch(
ctx1.getImageData(0, 0, image1.width, image1.height),
ctx2.getImageData(0, 0, image2.width, image2.height),
null,
image1.width,
image1.height
);
outputCtx.putImageData(diff, 0, 0);
setDifference(outputCanvas);
}
};

return (
<div>
<input type="file" onChange={handleFileChange(setImage1)} />
<input type="file" onChange={handleFileChange(setImage2)} />
<button onClick={() => { compareImages() }}>Compare Images</button>
<canvas ref={canvas1Ref} />
<canvas ref={canvas2Ref} />
{difference && <canvas ref={outputCanvasRef} />}
</div>
);
}
export default Tab1;

可以使用像这样的扩展运算符{...props}来传递一个条件ref

const itemProps = difference ? { ref: outputCanvasRef } : {};
<canvas {...itemProps} />

在你的实现中有几个地方出了问题:

  • 您需要在没有任何条件的情况下渲染output canvas,以便它始终可用于比较功能。
  • pixelmatch软件包要求您想要比较的图像始终具有相同的宽度&高度。要做到这一点,你可以使用宽度&两个图像1 &图2 .
  • 你需要将getImageData调用返回的数组缓冲区传递给pixelmatchgetImageData返回ImageData对象。你可以像这样访问数组缓冲区ImageData.data
  • 你应该传递ImageData对象的data字段给pixelmatch库的第三个参数作为参数,这样像素的差异就可以写在ImageData对象中。

解决方案

import { useRef, useState } from "react";
import pixelmatch from "pixelmatch";
const Tab1 = () => {
const [image1, setImage1] = useState(null);
const [image2, setImage2] = useState(null);
const [difference, setDifference] = useState(null);
const canvas1Ref = useRef(null);
const canvas2Ref = useRef(null);
const outputCanvasRef = useRef(null);
const handleFileChange = (setImage) => (event) => {
const file = event.target.files[0];
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
const image = new Image();
image.src = fileReader.result;
image.onload = () => setImage(image);
};
};
const compareImages = async () => {
if (image1 && image2) {
const canvas1 = canvas1Ref.current;
const canvas2 = canvas2Ref.current;
const outputCanvas = outputCanvasRef.current;
canvas1.width = image1.width;
canvas1.height = image1.height;
canvas2.width = image1.width;
canvas2.height = image1.height;
outputCanvas.width = image1.width;
outputCanvas.height = image1.height;
const ctx1 = canvas1.getContext("2d");
const ctx2 = canvas2.getContext("2d");
const outputCtx = outputCanvas.getContext("2d");
const diff = outputCtx.createImageData(image1.width, image1.height);
ctx1.drawImage(image1, 0, 0);
ctx2.drawImage(image2, 0, 0);

pixelmatch(
ctx1.getImageData(0, 0, image1.width, image1.height).data,
ctx2.getImageData(0, 0, image1.width, image1.height).data,
diff.data,
image1.width,
image1.height
);
outputCtx.putImageData(diff, 0, 0);
setDifference(diff);
}
};

return (
<div>
<input type="file" onChange={handleFileChange(setImage1)} />
<input type="file" onChange={handleFileChange(setImage2)} />
<button onClick={() => { compareImages() }}>Compare Images</button>
<canvas ref={canvas1Ref} />
<canvas ref={canvas2Ref} />
{<canvas ref={outputCanvasRef} />}
</div>
);
}
export default Tab1;

最新更新