我可以让Node.JS生成没有html页面的画布吗?

Wou*_*jke 5 javascript canvas node.js

我正在尝试制作一个Twitter机器人,该机器人会生成随机的RGB颜色,创建该颜色的图片并进行推文发送。我创建了一个可以生成和鸣叫随机rgb值的JS,以及一个可以生成随机颜色图片的javascript,但是我不确定如何将两者结合起来。

我的问题是,没有文档就无法生成PNG图像。如果我在使用Node.JS的服务器上运行脚本,则没有文档可以在其中创建画布。还有其他方法可以创建png图片(也许是通过将其临时保存到服务器上)并将其附加到推文上?

谢谢你的帮助!

这是我用于发布随机值的代码:

var Twit = require('twit')

var T = new Twit({
  consumer_key:         '###', 
  consumer_secret:      '###',
  access_token:         '###',
  access_token_secret:  '###'
})

function tweet() {
  //Generate a random colour
  var r = Math.floor((Math.random() * 256));
  var g = Math.floor((Math.random() * 256));
  var b = Math.floor((Math.random() * 256));
  var color = "rgb("+r+","+g+","+b+")";

  // tweet that colour
  T.post('statuses/update', { status: color }); 
}

setTimeout(tweet, 30000);
Run Code Online (Sandbox Code Playgroud)

这是一个JS脚本,可在网页上生成随机颜色的PNG文件:

var r = Math.floor((Math.random() * 256));
var g = Math.floor((Math.random() * 256));
var b = Math.floor((Math.random() * 256));
var color = "rgb("+r+","+g+","+b+")";

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

// draw box
context.beginPath();
context.moveTo(0, 00);
context.lineTo(0, 800);
context.lineTo(800, 800);
context.lineTo(800, 0);
context.closePath();
context.lineWidth = 5;
context.fillStyle = color;
context.fill();

// save canvas image as data url (png format by default)
var dataURL = canvas.toDataURL();

// set canvasImg image src to dataURL
// so it can be saved as an image
document.getElementById('canvasImg').src = dataURL;
Run Code Online (Sandbox Code Playgroud)

Pet*_*TNT 7

2020 年更新:

正如@Mike'Pomax'Kamermans 在评论中指出的那样,NodeJS 现在(自 v7 起)包含与URL浏览器相同的对象,可用于将画布数据 URI 放入然后保存到磁盘,类似于此答案:https: //stackoverflow.com/a/11335500/2138943

旧答案(对于 Node 版本 < 7)

您可以使用<canvas>由 JavaScript DOM 支持的 Node实现,例如带有jsDom 的node-canvas。例如,您的代码应如下所示:canvas

    var Canvas = require('canvas');
    var Image = Canvas.Image;
    var canvas = new Canvas(800, 800);
    var context = canvas.getContext('2d');
    var r = Math.floor((Math.random() * 256));
    var g = Math.floor((Math.random() * 256));
    var b = Math.floor((Math.random() * 256));
    var color = "rgb("+r+","+g+","+b+")";


    // draw box
    context.beginPath();
    context.moveTo(0, 00);
    context.lineTo(0, 800);
    context.lineTo(800, 800);
    context.lineTo(800, 0);
    context.closePath();
    context.lineWidth = 5;
    context.fillStyle = color;
    context.fill();

    // save canvas image as data url (png format by default)
    var dataURL = canvas.toDataURL();

    // set canvasImg image src to dataURL
    // so it can be saved as an image
    document.getElementById('canvasImg').src = dataURL;
Run Code Online (Sandbox Code Playgroud)

如果你想摆脱 jsDom 要求,你可以canvas.pngStream()像@josh3736 在评论中建议的那样使用(如果你没有对文档本身做任何其他事情,即你只需要画布)

画布#pngStream()

要创建 PNGStream,只需调用 canvas.pngStream(),流将开始发出数据事件,最后在完成时发出结束。如果发生异常,则发出错误事件。

var fs = require('fs'),
Run Code Online (Sandbox Code Playgroud)
  ,  out = fs.createWriteStream(__dirname + '/text.png')   
  , stream = canvas.pngStream();
Run Code Online (Sandbox Code Playgroud)
stream.on('data', function(chunk){out.write(chunk); });

stream.on('end', function(){console.log('saved png'); }); 
Run Code Online (Sandbox Code Playgroud)

目前仅支持同步流,但我们计划也支持异步流(当然:))。在此之前,Canvas#toBuffer(callback) 替代方案是使用 eio_custom() 进行异步的。

  • 这很好,但由于我们在服务器上,所以实际上没有理由使用数据 URL——只需将结果保存/提供为常规 PNG 文件(`canvas.pngStream()`)。 (2认同)