2

我已经在 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()方法内部。任何帮助深表感谢 !

提前致谢 !

4

2 回答 2

2
// Using view.toSVG() along with the npm package sharp worked well for me 


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

view.toSVG().then(async function (svg) {

    await sharp(Buffer.from(svg))
        .toFormat('png')
        .toFile('fileName.png')

}).catch(function(err) {
    console.error(err);
});
于 2020-06-05T11:54:26.087 回答
1

编辑:我设法解决了我的问题,我在这里发布 anwser 以备将来通知:

view.toSVG()我通过使用而不是 buggy将 View 对象直接渲染为 SVG 字符串,成功地实际生成了图形图片,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;
}
于 2020-04-28T06:45:46.493 回答