使用canvas创建桌面通知图像,只有一个图像可以从后台页面工作

Using canvas to create desktop notification images, only one image works from background page

本文关键字:图像 后台 工作 创建 canvas 桌面 通知 使用 有一个      更新时间:2023-09-26

我在后台页面中使用canvas为桌面通知的图像创建数据URL时遇到问题。

我想使用"图像"通知,它需要3:2的比例才能正确显示。我想使用的图像(来自hulu.com)的比例不同,所以我决定使用canvas元素从这些图像中创建相应的数据URL,以便比例正确。理论上是可行的,但是…

…如果我在后台页面中创建多个画布/通知,我会遇到问题。一个图像创建得很好,但其余的都是空的。

令人困惑的是,在一个新的选项卡中打开相同的背景页面(即完全相同的代码)会让一切正常:所有通知都是用从hulu.com加载的图像创建的。此外,只需将尺寸从360x240更改为300x200就可以了。最后,尽管它们是类似的电脑,具有相同的Chrome版本(34.0.1847.116),但它在工作中不需要修改就可以工作,而我自己的笔记本电脑上没有。

我在这篇文章的底部提供了一个测试扩展。基本上,它只有一个生成的背景页面。该页面的代码是:

var images = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
    "http://ib2.huluim.com/video/60366793?size=290x160&img=1",
    "http://ib4.huluim.com/video/60372951?size=290x160&img=1",
    "http://ib1.huluim.com/video/60365336?size=290x160&img=1",
    "http://ib3.huluim.com/video/60376290?size=290x160&img=1",
    "http://ib4.huluim.com/video/60377231?size=290x160&img=1",
    "http://ib4.huluim.com/video/60312203?size=290x160&img=1",
    "http://ib1.huluim.com/video/60376972?size=290x160&img=1",
    "http://ib4.huluim.com/video/60376971?size=290x160&img=1",
    "http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
for (var i = 0; i < 10; i++) {
    getDataURL(i);
}
/*
 * Gets the data URL for an image URL
 */
function getDataURL(i) {
    var img = new Image();
    img.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = 360;
        canvas.height = 240;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(this, 0, 0);
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);
        var dataURL = canvas.toDataURL('image/png');
        chrome.notifications.create('', {
            type: 'image',
            iconUrl: 'logo_128x128.png',
            title: String(i),
            message: 'message',
            imageUrl: dataURL
        }, function(id) {});
    }
    //img.src = chrome.extension.getURL('logo_128x128.png');;
    img.src = images[i];
}

img.src = ...的注释行是一个测试,它加载本地文件而不是远程文件。在这种情况下,将创建所有图像。

添加到画布上的红色矩形是为了表明问题不仅仅是远程图像:整个画布是空的,没有任何红色矩形。

如果你下载并添加下面的测试扩展,你应该会收到10个通知,但只有一个带有图像。

然后,要在新选项卡中打开背景页,您可以检查背景页,在控制台中键入以下内容:

chrome.extension.getURL('_generated_background_page.html')

右键单击URL,然后单击"在新选项卡中打开"(或窗口)。一旦打开,你应该会收到10个看起来不错的通知。

知道发生了什么事吗?我找不到任何与此相关的背景页的限制。任何帮助都将不胜感激,因为这已经让我发疯了!

此处提供的文件:https://www.dropbox.com/s/ejbh6wq0qixb7a8/canvastest.zip


编辑:根据@GameAlchemist的评论,我也尝试了以下方法:相同的getDataURL方法,但循环包裹在标志的onload中:

function loop() {
    for (var i = 0; i < 10; i++) {
        getDataURL(i);
    }
}
var logo = new Image();
logo.onload = function () {
    loop();
}
logo.src = chrome.extension.getURL('logo_128x128.png');

请记住create()方法是异步的,您应该使用带有的回调。回调可以调用下一个图像获取。

我建议分两步进行:

  1. 首先加载所有图像
  2. 处理图像队列

原因是,您可以通过这种方式更好地利用异步映像加载,而不是链接回调,这将迫使您加载一个映像和一个映像。

例如:

图像加载程序

var urls = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
    "http://ib2.huluim.com/video/60366793?size=290x160&img=1",
    "http://ib4.huluim.com/video/60372951?size=290x160&img=1",
    "http://ib1.huluim.com/video/60365336?size=290x160&img=1",
    "http://ib3.huluim.com/video/60376290?size=290x160&img=1",
    "http://ib4.huluim.com/video/60377231?size=290x160&img=1",
    "http://ib4.huluim.com/video/60312203?size=290x160&img=1",
    "http://ib1.huluim.com/video/60376972?size=290x160&img=1",
    "http://ib4.huluim.com/video/60376971?size=290x160&img=1",
    "http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
var images = [],            // store image objects
    count = urls.length;    // for loader
for (var i = 0; i < urls.length; i++) {
    var img = new Image;         // create image
    img.onload = loader;         // share loader handler
    img.src = urls[i];           // start loading
    images.push(img);            // push image object in array
}
function loader() {
    count--;
    if (count === 0) process();  // all loaded, start processing
}
//TODO need error handling here as well

与加载器的概念代码打交道

正在处理

现在,处理可以与加载隔离:

function process() {
    // share a single canvas (use clearRect() later if needed)
    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d'),
        current = 0;
    canvas.width = 360;
    canvas.height = 240;
    createImage();             // invoke processing for first image
    function createImage() {
        ctx.drawImage(images[current], 0, 0); // draw current image
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);
        chrome.notifications.create('', {
            type    : 'image',
            iconUrl : 'logo_128x128.png',
            title   : String(i),
            message : 'message',
            imageUrl: canvas.toDataURL()  // png is default
        },
        function(id) {                    // use callback
            current++;                    // next in queue
            if (current < images.length) {
                createImage();            // call again if more images
            }
            else {
                done();                   // we're done -> continue to done()
            }
        });
    }
}

免责声明:我没有测试Chrome扩展的测试环境,因此可能会出现打字错误

希望这能有所帮助!