Node.js 中内置的动画 gif 的背景图像

Posted

技术标签:

【中文标题】Node.js 中内置的动画 gif 的背景图像【英文标题】:Background image for animated gif built in Node.js 【发布时间】:2021-01-31 10:19:49 【问题描述】:

我对使用 node.js 以及 express 和 canvas 等软件包非常陌生,因此,如果我的代码中有任何明显的错误,并且如果我花一点时间理解任何问题或解决方案,我深表歉意。

我目前正在定制一个版本 - https://github.com/Nooshu/node-countdown-gif。一个画布生成的倒数计时器,用于电子邮件。我的自定义很少,到目前为止我所做的只是加载字体并从 url 添加更多内容以进行查询。

我遇到的问题是,如果可能的话,我想加载外部图像作为计时器后面的背景图像,而不是纯色或渐变背景,看起来应该是可能的但我就是无法让它工作。

这是生成具有纯色背景的计时器视觉效果的代码块。

if(typeof timeResult === 'object')
            for(let i = 0; i < this.frames; i++)
                // extract the information we need from the duration
                let days = Math.floor(timeResult.asDays());
                let hours = Math.floor(timeResult.asHours() - (days * 24));
                let minutes = Math.floor(timeResult.asMinutes()) - (days * 24 * 60) - (hours * 60);
                let seconds = Math.floor(timeResult.asSeconds()) - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60);

                // make sure we have at least 2 characters in the string
                days = (days.toString().length == 1) ? '0' + days : days;
                hours = (hours.toString().length == 1) ? '0' + hours : hours;
                minutes = (minutes.toString().length == 1) ? '0' + minutes : minutes;
                seconds = (seconds.toString().length == 1) ? '0' + seconds : seconds;

                // build the date string
                let string = [days, 'd ', hours, 'h ', minutes, 'm ', seconds, 's'].join('');

                // paint BG
                ctx.fillStyle = this.bg;
                ctx.fillRect(0, 0, this.w, this.h);

                // paint text
                ctx.fillStyle = this.textColor;
                ctx.fillText(string, this.halfWidth, this.halfHeight);

                // add finalised frame to the gif
                enc.addFrame(ctx);

                // remove a second for the next loop
                timeResult.subtract(1, 'seconds');
            
        

我需要在每个循环期间生成此背景图像,否则每个循环都将计时器层置于其顶部。我尝试了两种不同的方法来加载外部图像。第一次我根本无法上班,没有图像显示。见方法:

let img = new Canvas(this.w, this.h);
                img.src = 'https://via.placeholder.com/600x200.png';
                img.onload = function()
                  context.drawImage(img, 0, 0, this.w, this.h);
                

我的第二种方法取得了更大的成功,但仍然无法使其发挥作用。如果放置在代码中的较早位置(在 for 循环之前),它会成功加载图像但计时器不显示。如果放置在 for 循环中,它会为循环的每次迭代引发以下错误。这是代码块,后面跟着错误。注意:此错误仅在将代码块放入 for 循环时出现。

   let imgUrl = 'https://via.placeholder.com/'
    loadImage(imgUrl + image + '.png').then(image => 
        context.drawImage(image, 0, 0, 600, 200)

        const buffer = canvas.toBuffer('image/png')
        res.set( 'Content-Type': 'image/png' );
        res.send(buffer)
    )

Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()

有人可以支持我解决我的问题吗?

谢谢

【问题讨论】:

【参考方案1】:

我已经想通了。

在我的代码前面是一个初始化函数,它为构建计时器做准备,在这个函数中移动 onload 函数,然后将输出传递给一个允许在定义的 for 循环中放置 drawImage 函数时按预期工作的编码函数以上-

  if (imageBgSrc !== null) 
           let img = new Canvas.Image;
                img.src = imageBgSrc;
                img.onload = function() 
                $this.encode(timeResult, img, cb);
    
         else 
            this.encode(timeResult, null, cb);
        
encode: function (timeResult, image, cb) 

// Other code

if (image !== null) 
                    ctx.drawImage(image, 0, 0, this.width, this.height)
                
// Other code

【讨论】:

以上是关于Node.js 中内置的动画 gif 的背景图像的主要内容,如果未能解决你的问题,请参考以下文章

使用动画背景

重新启动动画 GIF 作为背景图像

如何使用 convert -crop 为动画 gif/放大图像添加更多背景?

IOS支持显示GIF动画图片吗? [复制]

Java:在其他动画 gif 上叠加/覆盖动画 gif

如何从电影创建动画 .gif?