我正在使用 HTML 和 JS 创建一个持久白板应用程序,用户在 cnavas 上的画布上绘图,单击“保存”,将画布图像数据存储到 mysql 数据库。当页面重新加载时,画布应该从数据库中获取存储的图像数据,并将其重新绘制在画布上,创建持久的白板。
获取函数工作正常,图像数据被正确检索并存储在数据结构中,但是当我重新加载页面时,图像不会被绘制回画布上。具体来说,当我使用
imageData.data.set(最新绘图)
imageData的长度与预期的latestDrawing的长度不匹配,我认为这是问题的原因;有谁知道如何使用预先存在的数据创建新的图像数据?
WhiteBoard.js 中的保存和重绘功能:
window.addEventListener('load', () => {
resize();
redraw();
window.addEventListener('click', handleOutsideClick);
document.addEventListener("mousedown", startdrawing);
document.addEventListener("mousemove", sketch);
document.addEventListener("mouseup", stopdrawing);
document.addEventListener("mouseout", stopdrawing);
window.addEventListener('resize', resize);
});
async function saveState() {
// console.log("before save")
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
await fetch('/WhiteBoard', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ type: 'canvasState', data: imageData }),
});
console.log("saved")
}
async function redraw() {
try {
const response = await fetch('/WhiteBoard');
var latestDrawing = await response.json();
if (latestDrawing) {
//get db data into readable image data form
latestDrawing = JSON.parse(latestDrawing.data);
//create a new blank image data
var imageData = ctx.createImageData(canvas.width, canvas.height);
imageData.data.set(latestDrawing);
ctx.putImageData(imageData, 0, 0);
}
} catch (error) {
console.error('Error:', error);
}
}
Server.js 中的 fetch 函数:
app.get('/WhiteBoard', (req,res) => {
// Set the content type to JSON
res.setHeader('Content-Type', 'application/json');
// Your existing query and response logic
db.query('SELECT * FROM canvas_state ORDER BY id DESC LIMIT 1', (error, results) => {
if (error) {
console.error(error);
res.status(500).send('Internal Server Error');
} else {
res.json(results[0]);
}
});
});
我尝试创建一个新的 Uint8ClampedArray,因为我阅读了另一篇建议这样做的文章,但是画布仍然没有重新绘制保存的图像
const dataArray = new Uint8ClampedArray(drawingData);
我认为后端与这里无关。一旦您可以通过
JSON.stringify()
传递数据,那么您就将问题隔离到了前端。
这是一种在一个画布上绘制内容、通过 JSON 字符串传递数据并将其写入另一个画布的方法:
const serializeCanvas = canvas => {
const ctx = canvasA.getContext("2d");
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const {buffer} = imageData.data;
const dataArray = Array.from(new Uint8ClampedArray(buffer));
return JSON.stringify(dataArray);
};
const writeCanvas = (canvas, data) => {
const ctx = canvas.getContext("2d");
const imageData = ctx.createImageData(canvas.width, canvas.height);
imageData.data.set(data);
ctx.putImageData(imageData, 0, 0);
};
const [canvasA, canvasB] = document.querySelectorAll("canvas");
// draw a square
canvasA.getContext("2d").fillRect(10, 10, 20, 20);
const json = serializeCanvas(canvasA);
// store `json` to the backend ...
// ... later on, restore it from a response:
writeCanvas(canvasB, JSON.parse(json));
canvas {
border: 1px solid black;
}
<canvas></canvas>
<canvas></canvas>