微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

画布中的图像不适用于 Chrome 扩展程序的图标 问题详情修复

如何解决画布中的图像不适用于 Chrome 扩展程序的图标 问题详情修复

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

<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);
};
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);
  };
  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,40);

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

所以它看起来像这样:

enter image description here

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

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

解决方法

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

ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.strokeRect(1,40);
ctx.putImageData(imageData,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);
  };

  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,50) });

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

});

修复

要解决此问题,只需将 setIcon 函数移动到 onload 事件,以便在图像加载并绘制到画布上后调用它。

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);
        chrome.browserAction.setIcon({imageData: ctx.getImageData(0,50)});
    };
});

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。