Search code examples
javascriptnode.jspngfabricjsfs

Fabric.JS with Node.JS - Exporting as PNG/JPEG


So I'm just messing around with Fabric.JS for Node.JS, not for the web, and I've managed to make a Static Canvas, and put a rectangle on it. Time to export. Here's my code for the creation of the canvas and adding of a rectangle:

var canvas = new fabric.StaticCanvas(null, {width: 200, height: 200})
var rect = new fabric.Rect({
  left: 100,
  top: 100,
  width: 100,
  height: 50,
  fill: "red"
})
canvas.add(rect)

Here's everything I've tried for exporting the image:

//Creates a PNG file that isn't generated correctly. It's as if it's corrupt. No program can open it
canvas.createPNGStream().on("data", function (chunk) {
  fs.createWriteStream(__dirname + "/output.png").write(chunk)
})

//Causes a crash
canvas.createJPEGStream().on("data", function (chunk) {
  fs.createWriteStream(__dirname + "/output.jpeg").write(chunk)
})

Error:
C:\Users\me\Documents\my project\node_modules\canvas\lib\jpegstream.js:44
    canvas[method](options.bufsize, options.quality, options.progressive, function(err, chunk){
                  ^

TypeError: canvas[method] is not a function
    at C:\Users\me\Documents\my project\node_modules\canvas\lib\jpegstream.js:44:19
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

//Same thing as first try^^, except it's a JPEG
canvas.createJPEGStream({quality: 100}).pipe(fs.createWriteStream(__dirname + "/output.jpeg"))

//This one makes the PNG file, but when it's opened, its 100% transparent. That's it. The rectangle I added isn't there. Canvas size is correct, however
canvas.createPNGStream().pipe(fs.createWriteStream(__dirname + "/output.png"))

Note: fabric.Canvas(null, {width: 200, height: 200}) also seems to work exactly the same as StaticCanvas, in this case

Note 2: This code:

var canvas = new fabric.createCanvasForNode(200, 200)

results in this error:

var canvas = new fabric.createCanvasForNode(200, 200)
             ^

TypeError: fabric.createCanvasForNode is not a constructor
    at Client.client.on.message (C:\Users\me\Documents\my project\index.js:31:14)
    at emitOne (events.js:115:13)
    at Client.emit (events.js:210:7)
    at MessageCreateHandler.handle (C:\Users\me\Documents\my project\node_modules\discord.js\src\client\websocket\packets\handlers\MessageCreate.js:9:34)
    at WebSocketPacketManager.handle (C:\Users\me\Documents\my project\node_modules\discord.js\src\client\websocket\packets\WebSocketPacketManager.js:103:65)
    at WebSocketConnection.onPacket (C:\Users\me\Documents\my project\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:330:35)
    at WebSocketConnection.onMessage (C:\Users\me\Documents\my project\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:293:17)
    at WebSocketClient.internalOnMessage (C:\Users\me\Documents\my project\node_modules\uws\uws.js:103:17)
    at native.client.group.onMessage (C:\Users\me\Documents\my project\node_modules\uws\uws.js:57:15)

Is there something I'm missing here? None of these methods seem to be working and it's about all I could find on Google. What's the correct way of exporting an image? It can be PNG or JPEG/JPG, preferably PNG, but JPEG/JPG will do. Any common format really.


Solution

  • Found the answer. canvas.createPNGStream().pipe(fs.createWriteStream(__dirname + "/output.png")) does actually work. The reason it was completely empty, is because it looks like canvas.add() isn't an instantanious action. All I did to figure this out was a setTimeout() before outputting the file. Hope this helps someone!