Проблема с canvas при использовании vega с nodejs (только на стороне сервера) - PullRequest
0 голосов
/ 20 апреля 2020

Я работаю уже несколько недель над ботом Discord, который в основном собирает статистику на сервере и выводит шаблоны. Чтобы улучшить его, я хотел, чтобы он генерировал графики в виде PNG, чтобы отправлять их обратно пользователю - короче говоря, без DOM. Для этого я использую vega (версия 5.10.1 - последняя) и node-canvas (версия 2.6.1 - последняя) с nodejs v12.16.1.

искал в интернете помощь по использованию vega и нашел пару противоречивых источников. Я использовал приведенный здесь пример кода: https://vega.github.io/vega/usage/

Дело в том, что я получаю эту ошибку:

TypeError: Cannot read property 'getContext' of null
message:"Cannot read property 'getContext' of null"
stack:"TypeError: Cannot read property 'getContext' of null
    at resize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3665:28)
    at CanvasRenderer.prototype$6.resize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3714:5)
    at CanvasRenderer.prototype$4.initialize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3294:17)
    at CanvasRenderer.prototype$6.initialize (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-scenegraph\build\vega-scenegraph.js:3709:28)
    at initializeRenderer (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-view\build\vega-view.js:657:8)
    at renderHeadless (e:\DEV\GIT REPOS\GITHUB\PERSO\JS\test-StatBot\node_modules\vega-view\build\vega-view.js:780:12)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async View.renderToCanvas [as toCanvas] (e:\DEV\GIT REPOS\GITHUB\P...

Вот код, который доставляет мне неприятности:

// Imports
const vega = require('vega');


// Render image from given graph spec (statsObject)
async function graphToImage (statsObject) {

    graphObject = new vega.View(vega.parse(statsObject), { renderer: 'none'});

    const pngName = generateFileName(10);

    removeExistingFile(pngName);

    graphObject.toCanvas().then(canvas => {

        console.log('Writing PNG to file...');
        writeFile(`../../../../generated/${pngName}.png`, canvas.toBuffer());

    }).catch(err => {

        console.log("Error writing PNG to file:");
        console.error(err);

    });


    return pngName;
}

Я действительно не знаю, как работают canvas или vega, и поэтому я понятия не имею, что может быть причиной этой проблемы и как ее исправить ... Однако проблема похоже, находится внутри toCanvas() метода. Любая помощь очень ценится!

Заранее спасибо!

1 Ответ

0 голосов
/ 28 апреля 2020

Редактировать: мне удалось исправить мою проблему, и я публикую здесь ответ для дальнейшего уведомления:

Мне удалось создать графическое изображение путем рендеринга объекта View прямо в строку SVG, используя view.toSVG() вместо глючной view.toCanvas(), которая прекрасно работала.

Затем все, что осталось сделать, это преобразовать полученную строку SVG в файл PNG, и на этом все.

Вот обновленный рабочий код:

// Imports
const vega = require('vega');


// Render image from given graph object
async function graphToImage (statsObject) {

    // Generate a new 10-char hex string
    const pngName = generateHexStringName(10);


    // Remove any existing file with the same name in order to prevent confusion
    removeExistingFile(pngName);


    var view = new vega.View(vega.parse(statsObject), {renderer: 'none'});


    // Generate an SVG string
    view.toSVG().then(async function (svg) {

        // Working SVG string
        console.log(svg);

        // Process obtained SVG string, e. g. write it to PNG file


    }).catch(function(err) {

        console.error(err);

    });


    // Return the name of the generated PNG file
    return pngName;
}
...