为什么 localStorage 中的 drawImage 不起作用?
Why does drawImage from localStorage not work?
使用 TypeScript,但我认为这不重要。
需要 Whosebug 新标签:localstorage
如果您通过 .drawImage 将 img 标签复制到 canvas,它可以正常工作。如果您从 localStorage 保存并加载它,您会得到:
drawImage:参数 1 无法转换为以下任何一项:HTMLImageElement、SVGImageElement、HTMLCanvasElement、HTMLVideoElement、ImageBitmap。
HTML:
<div id="app">
<img id="img0" src='https://ir.ebaystatic.com/rs/v/fxxj3ttftm5ltcqnto1o4baovyl.png' height='100' width='100'>
<canvas id="img1" height='100' width='100' style='border:1px solid #d3d3d3;'></canvas>
<canvas id="img2" height='100' width='100' style='border:1px solid #d3d3d3;'></canvas>
</div>
JS:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
localStorage.setItem('someStorageKey', imgSrc);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var img0: HTMLImageElement = localStorage.getItem('someStorageKey') as HTMLImageElement;
console.log('Image data loaded: ' + img0);
// copy img0 => img1
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
ctx1.drawImage(img0, 0, 0); //error: Argument 1 could not be converted to any of: HTMLImageElement...
}
localStorage.setItem 只接受字符串,所以任何不是字符串的东西在保存之前都会有 .toString()
运行,查看 MDN localStorage.setItem.
您是否考虑过将 img src 保存到 localStorage 并执行类似的操作来渲染它
而不是 img
html 元素,您应该在 localStorage
中只存储它的 src
属性。然后您只需要创建一个图像,将其 src
设置为存储在 localStorage 中的值,并在加载后在 canvas
上绘制它。像这样:
function saveImg(srcImgID) {
// save img0 to local storage
var img = document.getElementById(srcImgID);
var imgSrc = img.getAttribute('src');
localStorage.setItem('someStorageKey', imgSrc);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(img, 0, 0);
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
// load img0
var img0Src = localStorage.getItem('someStorageKey') as HTMLImageElement;
var img0 = new Image();
img0.src = img0Src;
img0.onload = function () {
ctx1.drawImage(img0, 0, 0);
}
}
如果要将整个元素保留在 localStorage
中,则必须使用 imgSrc.outerHTML
localStorage.setItem('someStorageKey', imgSrc.outerHTML);
然后通过特殊方式获取元素:(DOMParser MDN) and SO answer
new DOMParser().parseFromString(localStorage.getItem('someStorageKey') as HTMLImageElement, "text/html").body.childNodes[0];
并等待图像加载:
img0.onload = () => {
ctx1.drawImage(img0, 0, 0);
}
出于某种原因,我需要将图像附加到 <body>
才能正常工作。如果你也遇到这种情况,你可以立即删除图像(它可能是 JSFiddle):
document.body.append(img0);img0.remove();
完整代码:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
localStorage.setItem('someStorageKey', imgSrc.outerHTML);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var img0: HTMLImageElement = new DOMParser().parseFromString(localStorage.getItem('someStorageKey') as HTMLImageElement, "text/html").body.childNodes[0];
console.log('Image data loaded: ' + img0);
// copy img0 => img1
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
img0.onload = () => {
ctx1.drawImage(img0, 0, 0);
}document.body.append(img0);img0.remove();
}
至少在 JSFiddle 中找到了可行的解决方案:https://jsfiddle.net/Dustin_00/nb1j3fw0/70/
@Rojo 的解决方案也有效。但在我的 .NET Core 应用程序中都不起作用——只是一个空白图像。
<div id="app">
<img id="img0" src='https://ir.ebaystatic.com/rs/v/fxxj3ttftm5ltcqnto1o4baovyl.png' height='100' width='100'>
<canvas id="canvas1" height='100' width='100' style='border:2px solid #00f;'></canvas>
<canvas id="canvas2" height='100' width='100' style='border:2px solid #f00;'></canvas>
</div>
打字稿:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL;
}
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
var imgBase64 = getBase64Image(imgSrc);
localStorage.setItem('someStorageKey', imgBase64);
// copy img0 => canvas2 (red border)
var canvas2: HTMLCanvasElement = document.getElementById('canvas2') as HTMLCanvasElement;
//console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var imgData = localStorage.getItem('someStorageKey');
// copy img0 => canvas1 (blue border) from storage
var canvas1: HTMLCanvasElement = document.getElementById('canvas1') as HTMLCanvasElement;
//console.log('cavas1: ' + canvas1);
var ctx1 : HTMLCanvasElement = canvas1.getContext('2d');
//console.log('ctx1: ' + ctx1);
var imgFromStorage = new Image();
imgFromStorage.onload = function () {
//console.log('imgFromStorage: ' + imgFromStorage);
//console.log('imgFromStorage.src: ' + imgFromStorage.src);
ctx1.drawImage(imgFromStorage, 0, 0);
}
imgFromStorage.src = imgData;
}
使用 TypeScript,但我认为这不重要。
需要 Whosebug 新标签:localstorage
如果您通过 .drawImage 将 img 标签复制到 canvas,它可以正常工作。如果您从 localStorage 保存并加载它,您会得到:
drawImage:参数 1 无法转换为以下任何一项:HTMLImageElement、SVGImageElement、HTMLCanvasElement、HTMLVideoElement、ImageBitmap。
HTML:
<div id="app">
<img id="img0" src='https://ir.ebaystatic.com/rs/v/fxxj3ttftm5ltcqnto1o4baovyl.png' height='100' width='100'>
<canvas id="img1" height='100' width='100' style='border:1px solid #d3d3d3;'></canvas>
<canvas id="img2" height='100' width='100' style='border:1px solid #d3d3d3;'></canvas>
</div>
JS:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
localStorage.setItem('someStorageKey', imgSrc);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var img0: HTMLImageElement = localStorage.getItem('someStorageKey') as HTMLImageElement;
console.log('Image data loaded: ' + img0);
// copy img0 => img1
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
ctx1.drawImage(img0, 0, 0); //error: Argument 1 could not be converted to any of: HTMLImageElement...
}
localStorage.setItem 只接受字符串,所以任何不是字符串的东西在保存之前都会有 .toString()
运行,查看 MDN localStorage.setItem.
您是否考虑过将 img src 保存到 localStorage 并执行类似的操作来渲染它
而不是 img
html 元素,您应该在 localStorage
中只存储它的 src
属性。然后您只需要创建一个图像,将其 src
设置为存储在 localStorage 中的值,并在加载后在 canvas
上绘制它。像这样:
function saveImg(srcImgID) {
// save img0 to local storage
var img = document.getElementById(srcImgID);
var imgSrc = img.getAttribute('src');
localStorage.setItem('someStorageKey', imgSrc);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(img, 0, 0);
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
// load img0
var img0Src = localStorage.getItem('someStorageKey') as HTMLImageElement;
var img0 = new Image();
img0.src = img0Src;
img0.onload = function () {
ctx1.drawImage(img0, 0, 0);
}
}
如果要将整个元素保留在 localStorage
中,则必须使用 imgSrc.outerHTML
localStorage.setItem('someStorageKey', imgSrc.outerHTML);
然后通过特殊方式获取元素:(DOMParser MDN) and SO answer
new DOMParser().parseFromString(localStorage.getItem('someStorageKey') as HTMLImageElement, "text/html").body.childNodes[0];
并等待图像加载:
img0.onload = () => {
ctx1.drawImage(img0, 0, 0);
}
出于某种原因,我需要将图像附加到 <body>
才能正常工作。如果你也遇到这种情况,你可以立即删除图像(它可能是 JSFiddle):
document.body.append(img0);img0.remove();
完整代码:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
localStorage.setItem('someStorageKey', imgSrc.outerHTML);
// copy img0 => img2
var canvas2: HTMLCanvasElement = document.getElementById('img2') as HTMLCanvasElement;
console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var img0: HTMLImageElement = new DOMParser().parseFromString(localStorage.getItem('someStorageKey') as HTMLImageElement, "text/html").body.childNodes[0];
console.log('Image data loaded: ' + img0);
// copy img0 => img1
var canvas1: HTMLCanvasElement = document.getElementById('img1') as HTMLCanvasElement;
console.log('cavas1: ' + canvas1);
var ctx1 = canvas1.getContext('2d');
img0.onload = () => {
ctx1.drawImage(img0, 0, 0);
}document.body.append(img0);img0.remove();
}
至少在 JSFiddle 中找到了可行的解决方案:https://jsfiddle.net/Dustin_00/nb1j3fw0/70/
@Rojo 的解决方案也有效。但在我的 .NET Core 应用程序中都不起作用——只是一个空白图像。
<div id="app">
<img id="img0" src='https://ir.ebaystatic.com/rs/v/fxxj3ttftm5ltcqnto1o4baovyl.png' height='100' width='100'>
<canvas id="canvas1" height='100' width='100' style='border:2px solid #00f;'></canvas>
<canvas id="canvas2" height='100' width='100' style='border:2px solid #f00;'></canvas>
</div>
打字稿:
const img = document.querySelector("#img0");
img.setAttribute('crossOrigin','anonymous'); // mark image as safe for toDataURL
document.querySelector("#img0").onload = () => {
saveImg('img0');
};
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL;
}
function saveImg(srcImgID) {
// save img0 to local storage
var imgSrc = document.getElementById(srcImgID);
var imgBase64 = getBase64Image(imgSrc);
localStorage.setItem('someStorageKey', imgBase64);
// copy img0 => canvas2 (red border)
var canvas2: HTMLCanvasElement = document.getElementById('canvas2') as HTMLCanvasElement;
//console.log('cavas2: ' + canvas2);
var ctx2 = canvas2.getContext('2d');
ctx2.drawImage(imgSrc, 0, 0);
// load img0
var imgData = localStorage.getItem('someStorageKey');
// copy img0 => canvas1 (blue border) from storage
var canvas1: HTMLCanvasElement = document.getElementById('canvas1') as HTMLCanvasElement;
//console.log('cavas1: ' + canvas1);
var ctx1 : HTMLCanvasElement = canvas1.getContext('2d');
//console.log('ctx1: ' + ctx1);
var imgFromStorage = new Image();
imgFromStorage.onload = function () {
//console.log('imgFromStorage: ' + imgFromStorage);
//console.log('imgFromStorage.src: ' + imgFromStorage.src);
ctx1.drawImage(imgFromStorage, 0, 0);
}
imgFromStorage.src = imgData;
}