从数据库中存储的图像数据在画布上绘制图像

问题描述 投票:0回答:1

我正在使用 HTML 和 JS 创建一个持久白板应用程序,用户在画布上绘图并单击“保存”,这会将画布图像数据存储到 MySQL DB。当页面重新加载时,画布应该从数据库中获取存储的图像数据并将其重新绘制在画布上,从而创建一个持久的白板。

获取函数工作正常,图像数据被正确检索并存储在数据结构中。但是,当我重新加载页面时,图像不会被绘制回画布上。具体来说,当我使用

imageData.data.set(latestDrawing)
时,
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]);
    }
  });
});

我尝试创建一个

new Uint8ClampedArray
,因为我阅读了另一篇建议这样做的文章,但是画布仍然没有重新绘制保存的图像。

const dataArray = new Uint8ClampedArray(drawingData);
javascript html5-canvas
1个回答
0
投票

我认为后端与这里无关,尽管很高兴看到上下文和更广泛的用例。一旦您可以通过

JSON.stringify()
JSON.parse()
传递数据而不丢失信息,问题就变成纯粹的前端(目前 - 可能存在 API 或数据库问题,但这些问题具有不同的性质,应与前端隔离)画布图像数据获取/放置操作)。

这是一种在一个画布上绘制内容的方法,通过 JSON 字符串传递数据并将其写入另一个画布:

const canvasToArray = canvas => {
  const ctx = canvas.getContext("2d");
  const {data} = ctx.getImageData(0, 0, canvas.width, canvas.height);
  return [...new Uint8ClampedArray(data.buffer)];
};

const writeDataToCanvas = (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");
canvasA.getContext("2d").fillRect(10, 10, 20, 20);
const json = JSON.stringify(canvasToArray(canvasA));
// store `json` to the backend ...

// ... later on, restore it from a response:
writeDataToCanvas(canvasB, JSON.parse(json));
canvas {
  border: 1px solid black;
}
<canvas></canvas>
<canvas></canvas>

从中,您可以看到反序列化过程与您的尝试相比没有改变,但序列化过程确实按照您的建议使用了

Uint8ClampedArray
以及
Array.from()
或扩展。在原始代码中记录
JSON.stringify({ type: 'canvasState', data: imageData })
的结果应该表明画布数据未完成序列化过程。

现在,将数据 blob 存储在数据库中通常不是一个好主意。最好使用 S3 存储桶或其他一些优化的文件存储系统,并在数据库中存储数据的链接。

© www.soinside.com 2019 - 2024. All rights reserved.