Canvas 中的图像不适用于 Chrome 扩展程序的图标

Image in Canvas not working for Chrome Extension's icon

我正在将图像加载到 canvas 元素中。它在普通网页中工作正常:

<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.strokeRect(1, 1, 40, 40);

const image = new Image();
image.onload = function() {
  ctx.drawImage(image, 0, 0);
};
image.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKCgsJCYlJx8fLTEtJSk9Lj0uIyszODMsNygtLisBCgoKDQwNGg8PGjAlHyU3Nzc3LSstKy0tNS03Ky0rNSstLSsrKysrKy0rLSs3KysrKysrKysrKystKysrKysrK//AABEIACgAKAMBIgACEQEDEQH/xAAbAAACAwADAAAAAAAAAAAAAAAABwQFBgECA//EACwQAAEDAwMCBQMFAAAAAAAAAAECAwQABREGITESQRMyUYGRB2FxFCKhsfD/xAAYAQADAQEAAAAAAAAAAAAAAAADBAUCAf/EACERAQACAQMEAwAAAAAAAAAAAAEAAhEDEjEhIkFhBBNR/9oADAMBAAIRAxEAPwBkOftBpa631DNFxNut7gQGgC6oKG5PAwQcf2c0y3k9W1YhjS8ebrK5uzUlbI6SEFWAolI5x2GDtQb4qZeJug2cRXSZbxdUk8jY9wR6D/dq0Wgb/IjahELBW1K2wnYJUBscfgYprHTNnZaPh2+MAeR4YOfmsRq20MQHm7jbkoiyWT1pW2MdWD5TjkHg0G/yASqYz5hzQUbDxGTDUFLQHBsVDNFRbNJTKYjvo4WlKwD6EAiijHEBJ4Tk1RS/1LM6XIhNdTqkpSU4BJwSBsSABwck8eu1X6DsKgTpTEOSpxTiAQ0XFpzkhI745x965rjtz4m9BN2HmQTMuItSDKCG5jp6AANhnOD/ABWQ1HGujkN8ziQhtJ82CCexBASR+CD23qVqLVanoZXCgPupQ6lQcW2UjA5I3ya637UES6WBEjxC0yD0vhaSCg4BORydjnbmkLi+/wAj4AdekudLPOLs0Z0I6Q2kITg+YAAZ98UV7abuFnetjEa2XCLI8NsDDagCTyT0ncb5O9FUqUdvdJmojbti2vv1IvVxBEDMCOT0gMnKycZAKud9uMd+ap7Lf5zWpo9xlzXXFuKCFuOkqy2Tg5z2HOAexoopy1K7GJUvbeRm6muao8xgB5wNEAuNNxwsK98bUvPqFd3JCVRgUhouZSlPdIHJ98fFFFS9KlXUrKupe31sxkYEKCgSkjfIzkff5rmiiqklq5n/2Q==';

https://codepen.io/adsfdsfhdsafkhdsafjkdhafskjds/pen/abBqLdQ

然而,当我尝试使用相同的代码为我的 Chrome 扩展程序设置图标时,它有矩形但没有图像。在后台脚本中:

chrome.webNavigation.onCompleted.addListener(() => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 50;
  canvas.height = 50;

  const image = new Image();
  image.onload = function() {
    ctx.drawImage(image, 0, 0);
  };
  image.src = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKCgsJCYlJx8fLTEtJSk9Lj0uIyszODMsNygtLisBCgoKDQwNGg8PGjAlHyU3Nzc3LSstKy0tNS03Ky0rNSstLSsrKysrKy0rLSs3KysrKysrKysrKystKysrKysrK//AABEIACgAKAMBIgACEQEDEQH/xAAbAAACAwADAAAAAAAAAAAAAAAABwQFBgECA//EACwQAAEDAwMCBQMFAAAAAAAAAAECAwQABREGITESQRMyUYGRB2FxFCKhsfD/xAAYAQADAQEAAAAAAAAAAAAAAAADBAUCAf/EACERAQACAQMEAwAAAAAAAAAAAAEAAhEDEjEhIkFhBBNR/9oADAMBAAIRAxEAPwBkOftBpa631DNFxNut7gQGgC6oKG5PAwQcf2c0y3k9W1YhjS8ebrK5uzUlbI6SEFWAolI5x2GDtQb4qZeJug2cRXSZbxdUk8jY9wR6D/dq0Wgb/IjahELBW1K2wnYJUBscfgYprHTNnZaPh2+MAeR4YOfmsRq20MQHm7jbkoiyWT1pW2MdWD5TjkHg0G/yASqYz5hzQUbDxGTDUFLQHBsVDNFRbNJTKYjvo4WlKwD6EAiijHEBJ4Tk1RS/1LM6XIhNdTqkpSU4BJwSBsSABwck8eu1X6DsKgTpTEOSpxTiAQ0XFpzkhI745x965rjtz4m9BN2HmQTMuItSDKCG5jp6AANhnOD/ABWQ1HGujkN8ziQhtJ82CCexBASR+CD23qVqLVanoZXCgPupQ6lQcW2UjA5I3ya637UES6WBEjxC0yD0vhaSCg4BORydjnbmkLi+/wAj4AdekudLPOLs0Z0I6Q2kITg+YAAZ98UV7abuFnetjEa2XCLI8NsDDagCTyT0ncb5O9FUqUdvdJmojbti2vv1IvVxBEDMCOT0gMnKycZAKud9uMd+ap7Lf5zWpo9xlzXXFuKCFuOkqy2Tg5z2HOAexoopy1K7GJUvbeRm6muao8xgB5wNEAuNNxwsK98bUvPqFd3JCVRgUhouZSlPdIHJ98fFFFS9KlXUrKupe31sxkYEKCgSkjfIzkff5rmiiqklq5n/2Q==';
 
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'green';
  ctx.strokeRect(1, 1, 40, 40);

  chrome.browserAction.setIcon({
    imageData: ctx.getImageData(0, 0, 50, 50),
  });
});

所以它看起来像这样:

我在网页或后台脚本的控制台中没有看到任何错误。我也尝试加载本地和删除图像(不是 base64 编码)但没有任何变化:

image.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmuyeAhT_2puKqL7azw3al2li8Nd8gIvppig&usqp=CAU';
image.src = 'images/48-time.png';

根据您的描述(和代码),当您执行 ctx.getImageData 时图像似乎没有加载...我会执行 browserAction.setIconctx.drawImage 之后的同一个 onload 函数中,下面是我们在 onload.

中进行所有绘图的示例

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const image = new Image();
image.onload = function() {
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'green';
  ctx.strokeRect(1, 1, 40, 40);
  ctx.drawImage(image, 0, 0);
  // Add other browserAction.setIcon logic here
};
image.src = 'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAOElEQVR42u3OQREAAAQAMILoH0ckUrjz2BIsu2risRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFLyxCZNRaZIFESsAAAAASUVORK5CYII=';
<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

我确实将您的图片换成较小的图片,只是为了减少代码。
你可以改回你的


另一种选择是使用 putImageData 而不是 drawImage

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const arr = new Uint8ClampedArray([214,212,189,255,214,211,189,255,213,209,191,255,215,209,194,255,218,210,199,255,218,209,201,255,216,205,200,255,214,203,198,255,213,204,198,255,197,189,179,255,216,210,196,255,211,207,188,255,208,205,180,255,172,171,141,255,165,166,132,255,145,144,117,255,89,82,74,255,113,102,100,255,99,88,79,255,88,76,61,255,69,58,37,255,97,88,63,255,79,73,47,255,57,55,31,255,59,61,41,255,215,213,191,255,213,211,190,255,214,210,192,255,215,209,195,255,217,210,199,255,217,209,200,255,215,206,199,255,212,203,197,255,199,190,183,255,224,217,207,255,194,188,174,255,169,165,146,255,182,179,155,255,170,169,141,255,131,132,100,255,136,134,110,255,94,87,80,255,87,77,76,255,78,68,61,255,68,57,46,255,75,66,50,255,80,73,54,255,79,75,56,255,65,64,46,255,90,92,79,255,215,214,195,255,213,211,193,255,213,210,194,255,215,210,196,255,215,210,197,255,215,210,199,255,213,206,197,255,210,203,194,255,217,210,200,255,200,193,181,
  255,190,184,169,255,193,189,171,255,108,104,83,255,60,58,34,255,38,36,11,255,56,53,34,255,91,85,80,255,68,61,61,255,71,63,61,255,60,52,48,255,74,66,61,255,48,42,36,255,57,55,50,255,58,58,55,255,72,75,73,255,215,215,199,255,213,212,197,255,213,211,197,255,213,211,197,255,213,211,197,255,213,209,197,255,210,206,194,255,208,203,191,255,187,182,169,255,187,182,168,255,199,194,179,255,170,166,149,255,74,70,52,255,68,64,46,255,86,82,63,255,69,65,51,255,67,62,58,255,59,53,54,255,70,63,65,255,66,59,62,255,61,55,59,255,31,26,32,255,37,34,43,255,49,49,58,255,44,47,55,255,215,215,205,255,213,213,202,255,212,212,201,255,211,211,199,255,212,211,198,255,210,209,195,255,207,207,191,255,205,203,187,255,196,194,178,255,202,199,183,255,145,142,126,255,57,52,38,255,50,45,32,255,47,42,29,255,46,41,29,255,44,38,29,255,52,47,43,255,56,50,51,255,50,44,48,255,57,51,60,255,43,38,51,255,46,42,58,255,39,36,55,255,46,46,64,
  255,56,58,72,255,215,216,210,255,213,214,207,255,210,213,204,255,210,212,201,255,210,212,199,255,208,210,195,255,205,207,189,255,202,204,184,255,213,213,194,255,181,180,162,255,125,122,106,255,57,52,39,255,73,66,56,255,61,54,46,255,73,65,59,255,82,73,68,255,76,68,63,255,66,58,56,255,34,27,29,255,41,34,42,255,35,29,42,255,62,56,73,255,45,40,59,255,39,35,52,255,59,57,69,255,215,217,214,255,213,215,211,255,210,214,207,255,208,213,202,255,207,212,198,255,206,210,193,255,202,207,187,255,200,203,182,255,189,191,170,255,169,169,149,255,123,120,104,255,67,62,49,255,63,56,47,255,92,83,78,255,105,94,92,255,84,71,69,255,95,82,74,255,74,61,53,255,46,35,32,255,40,31,32,255,44,36,42,255,56,48,56,255,50,42,50,255,42,34,40,255,49,40,42,255,215,218,217,255,213,216,214,255,209,214,209,255,208,214,205,255,206,212,199,255,204,211,194,255,201,207,187,255,198,203,181,255,194,197,175,255,166,166,146,255,52,49,32,255,36,
  30,17,255,88,79,71,255,98,86,82,255,59,44,43,255,109,92,89,255,85,66,54,255,68,49,35,255,67,51,41,255,52,39,31,255,63,51,46,255,45,33,29,255,60,47,40,255,66,51,41,255,64,46,32,255,214,217,217,255,212,216,215,255,211,216,212,255,208,213,207,255,204,211,200,255,199,207,192,255,196,203,184,255,194,200,179,255,182,186,164,255,156,157,136,255,52,49,32,255,50,42,29,255,78,65,57,255,103,87,82,255,96,78,75,255,74,52,46,255,86,60,44,255,83,56,37,255,83,60,42,255,95,75,57,255,109,92,73,255,112,96,73,255,102,83,57,255,91,68,37,255,120,92,56,255,214,217,217,255,212,216,215,255,211,216,213,255,208,213,208,255,204,211,202,255,200,208,195,255,197,204,188,255,195,201,183,255,211,214,195,255,142,142,124,255,43,39,22,255,74,65,50,255,68,53,42,255,74,54,45,255,105,83,76,255,143,117,105,255,170,138,117,255,172,140,115,255,176,148,124,255,187,163,137,255,199,178,148,255,207,186,150,255,209,185,142,255,210,179,131,255,
  197,159,106,255,214,217,215,255,213,216,214,255,211,216,212,255,208,213,208,255,204,211,204,255,201,208,199,255,198,204,193,255,198,203,190,255,190,192,177,255,146,144,128,255,54,47,31,255,79,66,50,255,75,56,41,255,142,119,104,255,203,177,161,255,228,198,179,255,241,205,180,255,243,206,178,255,239,208,179,255,233,207,175,255,225,202,165,255,221,197,152,255,224,194,141,255,230,193,132,255,234,186,121,255,215,217,212,255,214,216,212,255,212,215,211,255,208,213,209,255,206,211,207,255,202,208,203,255,201,206,200,255,201,204,196,255,200,200,190,255,190,186,173,255,83,73,57,255,84,68,50,255,109,88,67,255,216,190,167,255,249,220,195,255,228,195,168,255,243,205,176,255,245,208,178,255,243,212,182,255,236,210,177,255,229,205,168,255,226,200,156,255,232,198,144,255,241,198,135,255,253,199,129,255,218,218,210,255,215,216,209,255,214,215,210,255,210,212,209,255,206,210,209,255,204,208,208,255,204,207,207,255,
  205,205,204,255,218,216,211,255,199,192,183,255,81,68,53,255,102,84,63,255,164,140,114,255,226,197,166,255,227,196,160,255,229,195,158,255,245,208,175,255,245,210,180,255,243,215,187,255,243,219,192,255,242,219,191,255,243,216,181,255,246,210,165,255,252,205,150,255,244,185,118,255,219,218,207,255,217,217,208,255,215,215,209,255,211,212,209,255,208,211,211,255,207,209,213,255,207,208,212,255,208,207,211,255,208,204,203,255,197,188,182,255,96,81,67,255,117,96,74,255,199,173,142,255,230,199,161,255,238,204,159,255,255,226,183,255,255,220,185,255,252,220,192,255,247,221,198,255,244,222,202,255,240,219,200,255,236,210,186,255,233,196,162,255,234,184,139,255,238,175,115,255,219,218,205,255,218,217,206,255,214,213,207,255,211,211,210,255,209,210,213,255,209,210,216,255,209,209,217,255,211,208,215,255,222,216,219,255,221,210,206,255,144,128,114,255,134,111,87,255,208,181,145,255,230,197,153,255,252,216,165,
  255,250,214,165,255,245,212,177,255,243,214,189,255,242,219,202,255,242,222,211,255,241,222,214,255,242,217,206,255,243,206,186,255,249,199,166,255,255,196,147,255,221,217,206,255,220,216,207,255,216,213,208,255,212,211,210,255,209,210,214,255,209,209,217,255,210,210,218,255,212,210,216,255,227,222,225,255,203,194,189,255,147,131,117,255,144,122,98,255,218,190,154,255,222,189,145,255,255,218,166,255,238,203,154,255,245,215,179,255,243,218,193,255,242,220,205,255,241,220,212,255,236,214,211,255,234,206,202,255,237,199,186,255,244,196,168,255,244,184,139,255,224,215,209,255,223,215,210,255,220,214,212,255,217,214,214,255,214,214,217,255,213,215,220,255,213,215,220,255,215,216,219,255,211,210,208,255,227,221,214,255,153,140,125,255,138,118,94,255,204,177,145,255,253,221,182,255,235,198,154,255,240,206,162,255,244,219,180,255,242,221,191,255,238,215,197,255,238,212,203,255,237,207,204,255,246,211,207,
  255,245,205,190,255,243,198,169,255,236,188,140,255,224,215,211,255,223,215,212,255,220,214,213,255,217,214,214,255,215,215,216,255,214,215,217,255,215,216,218,255,217,217,216,255,220,218,213,255,223,216,206,255,180,167,150,255,112,92,68,255,215,187,157,255,244,211,176,255,249,211,172,255,255,224,183,255,244,218,178,255,244,220,186,255,246,218,195,255,241,209,195,255,239,203,194,255,253,213,203,255,247,204,186,255,221,178,146,255,221,178,129,255,221,217,215,255,220,216,214,255,218,215,214,255,217,216,215,255,216,216,215,255,216,216,215,255,218,217,215,255,221,218,213,255,238,232,223,255,212,201,188,255,175,159,140,255,182,160,136,255,205,176,146,255,224,190,156,255,223,185,147,255,207,169,129,255,205,172,131,255,211,179,141,255,235,200,170,255,237,200,175,255,236,195,175,255,244,201,179,255,229,185,158,255,180,134,100,255,168,124,78,255,217,218,218,255,217,217,216,255,217,217,216,255,216,216,214,
  255,218,217,214,255,220,218,214,255,223,218,212,255,225,218,209,255,211,200,188,255,231,215,199,255,210,189,168,255,170,144,119,255,217,186,157,255,159,124,92,255,181,143,107,255,162,123,85,255,144,105,65,255,158,119,79,255,214,173,136,255,239,196,162,255,242,198,164,255,225,179,145,255,206,159,123,255,156,109,71,255,162,116,73,255,213,220,220,255,214,220,220,255,214,218,217,255,216,218,215,255,219,218,214,255,223,219,211,255,227,219,209,255,231,219,206,255,248,232,216,255,206,185,166,255,219,194,171,255,154,124,98,255,185,151,122,255,210,173,143,255,238,199,167,255,176,135,100,255,129,85,48,255,143,97,57,255,214,167,125,255,250,203,159,255,255,209,162,255,212,164,117,255,200,152,106,255,179,130,87,255,153,105,65,255,210,221,222,255,211,221,221,255,213,220,219,255,216,219,216,255,220,220,213,255,225,220,210,255,230,219,206,255,235,219,203,255,234,214,195,255,188,163,141,255,216,187,163,255,192,
  159,133,255,220,183,155,255,231,193,164,255,112,73,43,255,124,82,51,255,166,120,87,255,177,128,91,255,231,181,137,255,249,200,150,255,255,212,156,255,199,150,93,255,202,152,99,255,217,167,121,255,223,173,135,255,208,224,225,255,208,222,223,255,212,221,220,255,216,221,217,255,221,221,213,255,226,221,209,255,233,221,206,255,239,221,202,255,250,226,205,255,181,152,128,255,240,208,183,255,210,174,148,255,231,193,166,255,214,174,147,255,201,161,134,255,252,211,183,255,211,165,139,255,223,175,144,255,250,203,160,255,235,188,136,255,253,206,145,255,190,142,79,255,199,150,92,255,236,184,136,255,226,173,137,255,207,224,226,255,208,223,224,255,210,222,220,255,215,221,217,255,220,221,213,255,227,222,210,255,234,221,205,255,239,221,201,255,237,212,190,255,249,220,196,255,198,165,140,255,194,158,132,255,224,185,159,255,255,216,189,255,241,201,174,255,228,188,163,255,235,193,172,255,253,210,185,255,255,221,
  182,255,224,181,130,255,249,205,144,255,189,142,79,255,198,149,91,255,237,185,137,255,255,204,170,255,204,221,222,255,209,223,223,255,214,226,223,255,218,226,221,255,222,223,216,255,226,222,211,255,232,221,207,255,239,222,204,255,244,222,201,255,240,212,189,255,220,188,164,255,212,176,151,255,228,190,163,255,241,201,174,255,247,206,179,255,254,214,190,255,254,217,202,255,244,207,189,255,235,198,165,255,242,204,159,255,233,194,138,255,185,142,83,255,
  175,127,72,255,223,171,124,255,255,212,178,255])
const imageData = new ImageData(arr, 25, 25);

ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.strokeRect(1, 1, 40, 40);
ctx.putImageData(imageData, 0, 0);
<canvas id="canvas" width="50" height="50" style="border:1px solid #000000;">
</canvas>

我确实将您的图像缩小到 25x25 以减少数组中的数据

JS代码执行是异步的

您在绘制图像之前设置图标。

onLoad 事件异步运行,这意味着 onload 事件在当前执行完成之前不会触发。

问题详情

评论描述了正在发生的事情

chrome.webNavigation.onCompleted.addListener(() => { 

  //-------------------------------------------------------------------
  // start of onComplete. JS is blocking and no events will fire while code is executing.

  const canvas = document.createElement('canvas');
  const ctx = ... set up canvas
  const image = new Image();

  image.onload = function() {   // << This will not be called until onCompleted has returned
    ctx.drawImage(image, 0, 0);
  };

  image.src = ... the data URL 

  // You call setIcon before onCompleted has returned and thus there is nothing in the canvas
  chrome.browserAction.setIcon({ imageData: ctx.getImageData(0, 0, 50, 50) });

  // end of. onComplete returns
  //-------------------------------------------------------------------

});

修复

要修复,只需将 setIcon 函数移动到 onload 事件,以便在图像加载并绘制到 canvas 后调用它。

chrome.webNavigation.onCompleted.addListener(() => { 
    const ctx = Object.assign(
             document.createElement('canvas'), {width: 50, height: 50}
        ).getContext("2d");
    const image = new Image();
    image.src = // ... the data URL 
    image.addEventListener("load", () => {
        ctx.drawImage(image, 0, 0);
        chrome.browserAction.setIcon({imageData: ctx.getImageData(0, 0, 50, 50)});
    };
});

您可以在设置 onload 之前或之后设置 image.src 因为 onload 在当前执行完成之前不会触发