Встроенное фоновое изображение для анимированного gif Node.js

#javascript #node.js #canvas

#javascript #node.js #холст

Вопрос:

Я очень новичок в работе с node.js и такие пакеты, как express и canvas, поэтому я приношу извинения, если в моем коде есть какие-либо вопиюще очевидные ошибки и если мне потребуется немного времени, чтобы разобраться в каких-либо вопросах или решениях.

В настоящее время я работаю над настройкой версии — https://github.com/Nooshu/node-countdown-gif . Сгенерированный canvas таймер обратного отсчета для использования в электронных письмах. Мои настройки минимальны, все, что я сделал до сих пор, это загрузить шрифт и добавить еще немного из 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');
            }
        }
  

Мне нужно, чтобы это фоновое изображение создавалось во время каждого цикла, в противном случае таймер накладывается поверх каждого цикла. Я попробовал 2 разных метода, которые я видел для загрузки во внешнее изображение. Сначала я вообще не мог приступить к работе, изображение не отображалось. См. Метод :

 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 внутри этой функции, а затем передавая выходные данные функции encode, которой разрешено работать должным образом при размещении функции drawImage в цикле for, определенном выше —

   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
}