IndexedDB storeDrawing对象时发生catch报 DOMException: Failed to execute ‘put‘ on ‘IDBObjectStore‘: HTMLCan

IndexedDB storeDrawing对象时发生catch报 DOMException: Failed to execute 'put' on 'IDBObjectStore': HTMLCanvasElement object could not be cloned. at eval (webpack-internal:///./src/utils/indexedDB.js:44:27) at new Promise (<anonymous>) at storeDrawing (webpack-internal:///./src/utils/indexedDB.js:34:10) at eval (webpack-internal:///./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-41.use[1]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/MxShow.vue?vue&type=script&lang=ts:680:89) 是什么原因

你遇到的错误提示:DOMException: Failed to execute 'put' on 'IDBObjectStore': HTMLCanvasElement object could not be cloned. 说明了你在使用 IndexedDB 存储数据时,尝试存储 HTMLCanvasElement 对象,而 HTMLCanvasElement 是一种不能直接克隆或序列化的 DOM 对象。

为什么会出现这个问题?

IndexedDB 使用结构化克隆算法(Structured Clone Algorithm)来存储和传输对象。这个算法支持存储大多数常见的 JavaScript 对象,如 ArrayObjectDateBlob 等,但不支持某些 DOM 元素和其他复杂对象(例如 HTMLCanvasElementWindowFunctionHTMLImageElement 等)。

HTMLCanvasElement 是一个DOM节点,不能直接被结构化克隆,因此在你尝试将它存储到 IndexedDB 时,会抛出 DOMException 错误。

解决方案

为了能够存储画布数据,你需要先将 HTMLCanvasElement 的内容提取成一种可以被结构化克隆的格式。通常做法是将画布转换成 ImageData 或者 Blob,然后再存储到 IndexedDB。

方法1:将 HTMLCanvasElement 转换为 Blob

你可以使用 canvas.toBlob() 或者 canvas.toDataURL() 来将画布内容转换为 BlobDataURL,这样就能避免直接存储 HTMLCanvasElement,并且可以将 Blob 存储到 IndexedDB。


javascriptCopy Code

function storeDrawing(canvas) { return new Promise((resolve, reject) => { // 将 canvas 转换为 Blob canvas.toBlob((blob) => { if (blob) { // 在此存储 Blob 到 IndexedDB let dbRequest = indexedDB.open('MyDatabase'); dbRequest.onsuccess = function(event) { let db = event.target.result; let transaction = db.transaction(['drawings'], 'readwrite'); let objectStore = transaction.objectStore('drawings'); // 这里存储一个包含 Blob 数据的对象 let drawingData = { id: Date.now(), // 唯一标识符 imageBlob: blob // 存储 Blob 数据 }; let putRequest = objectStore.put(drawingData); putRequest.onsuccess = function() { resolve('Canvas drawing stored successfully.'); }; putRequest.onerror = function(event) { reject('Failed to store drawing: ' + event.target.error); }; }; dbRequest.onerror = function(event) { reject('Failed to open database: ' + event.target.error); }; } else { reject('Failed to convert canvas to Blob.'); } }); }); }

方法2:将 HTMLCanvasElement 转换为 DataURL

另一种方式是将画布转换为 DataURL,这通常是一种 base64 编码的字符串,适合较小的图像数据存储。然后可以将 DataURL 存储到 IndexedDB 中。


javascriptCopy Code

function storeDrawing(canvas) { return new Promise((resolve, reject) => { // 将 canvas 转换为 DataURL const dataURL = canvas.toDataURL(); // 存储 DataURL 到 IndexedDB let dbRequest = indexedDB.open('MyDatabase'); dbRequest.onsuccess = function(event) { let db = event.target.result; let transaction = db.transaction(['drawings'], 'readwrite'); let objectStore = transaction.objectStore('drawings'); let drawingData = { id: Date.now(), imageDataURL: dataURL // 存储 DataURL }; let putRequest = objectStore.put(drawingData); putRequest.onsuccess = function() { resolve('Canvas drawing stored successfully.'); }; putRequest.onerror = function(event) { reject('Failed to store drawing: ' + event.target.error); }; }; dbRequest.onerror = function(event) { reject('Failed to open database: ' + event.target.error); }; }); }

关键区别

  • Blob:适合存储二进制数据,适合较大的图像。
  • DataURL:适合存储小型图像,它会将图像数据编码为一个字符串,适合存储在数据库中,但它可能会比 Blob 占用更多的空间,因为它是 base64 编码的。

总结

你不能直接将 HTMLCanvasElement 存储到 IndexedDB 中,因为它无法被结构化克隆。需要先将画布转换为 BlobDataURL,然后存储转换后的数据。根据你的需求选择适合的方法(Blob 适合较大图像,DataURL 适合较小图像)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值