Skip to content

Canvas acquired via createCanvasForNode is broken #3885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
microDimensions opened this issue Apr 25, 2017 · 53 comments
Closed

Canvas acquired via createCanvasForNode is broken #3885

microDimensions opened this issue Apr 25, 2017 · 53 comments

Comments

@microDimensions
Copy link

Hello,

When working with the v2.0.0-beta.1 version of fabric on the server side, the node canvas acquired via createCanvasForNode does not seem to behave like a node canvas acquired via "new Canvas", although createCanvasForNode seemingly creates a valid node canvas via "new Canvas" as well. Below is the sample SERVER SIDE code required to re-create the issue

Notes:
Using our own built version of node-canvas, since the pre-built one conflicts with sharp image processing library.
OS: Windows 7
Node version: 7.9

Here is the file used for the test case:
honey_im_subtle

let Canvas = require('canvas');
let fabric = require('fabric').fabric;
fabric.canvasModule = 'canvas';

var fs = require('fs');

fs.readFile("honey_im_subtle.png", function (err, data) {
    if (err) {
        return console.log(err);
    }

    let fabric_canvas = fabric.createCanvasForNode(179, 132);

    let node_canvas = fabric_canvas.nodeCanvas;

    // using a newly created canvas works
    //let node_canvas = new Canvas(179, 132);

    let background_img = new Canvas.Image;
    background_img.src = data;

    let ctx = node_canvas.getContext('2d');
    ctx.drawImage(background_img, 0, 0, 179, 132); // fails

    // ensure the image was drawn to canvas
    let out = fs.createWriteStream(__dirname + '/canvas.png');
    let stream = node_canvas.pngStream();

    stream.on('data', function (chunk) {
        out.write(chunk);
    });

    stream.on('end', function () {
        console.log('saved canvas');
    });
});

The error message reads "Image or Canvas expected". I am attempting now to access the node canvas directly only because the following two attempts fail with the exact same error:

  • Setting a background image on the fabric canvas via SetBackgroundImage
  • Adding an image to the fabric canvas via "add"

Any help would be greatly appreciated!

Thomas

@asturur
Copy link
Member

asturur commented Dec 2, 2017

we removed canvasForNode completely, please ask if you have any question. Use this issue even if is closed now

@asturur asturur closed this as completed Dec 2, 2017
@feuerste
Copy link

So how do we create a canvas for node now? http://fabricjs.com/fabric-intro-part-4#node still references the old way to do it...
Thanks for your help

@asturur
Copy link
Member

asturur commented Dec 11, 2017

new fabric.StaticCanvas() should do the trick.
I'll update tutorials

@feuerste
Copy link

Thank you, and what would be the equivalent of fabric_canvas.nodeCanvas.toBuffer(); ?

@asturur
Copy link
Member

asturur commented Dec 11, 2017

is not really available anymore, i m exposing some node-canvas methods with

    fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {
      var impl = fabric.jsdomImplForWrapper(this.lowerCanvasEl);
      return impl && impl.createJPEGStream(opts);
    };

i think you should do fabric.jsdomImplForWrapper(canvas.lowerCanvasEl).methodOfYourChoice

otherwise i should replicate every old and new node-canvas methods here and it does not really make sense to me.

@asturur
Copy link
Member

asturur commented Dec 11, 2017

now i feel sorry that i exposed those 2 and created an exception. i should have waited more.

@feuerste
Copy link

When I use
fabric.jsdomImplForWrapper(canvas.lowerCanvasEl).toBuffer()
I just get TypeError: fabric.jsdomImplForWrapper(...).toBuffer is not a function.
Do you know, what I am doing wrong?

@asturur
Copy link
Member

asturur commented Dec 11, 2017

what do you get when you do:
fabric.jsdomImplForWrapper(canvas.lowerCanvasEl)

isn't it a NodeCanvas instance?

@feuerste
Copy link

Hm, this seems to be the error, it's an HTMLCanvasElementImpl instance.

@feuerste
Copy link

(How) do I need to explicitly tell fabric to use node canvas?

@asturur
Copy link
Member

asturur commented Dec 11, 2017

so that can be my fault then, let me look at it better.
Jsdom uses node-canvas automatically, and i m trying to leverage differences to it.

@asturur
Copy link
Member

asturur commented Dec 12, 2017

ok i found it, applying a fix. i'll do the same for Image.

@feuerste
Copy link

Great, looking forward to your fixes!

@asturur
Copy link
Member

asturur commented Dec 12, 2017

#4554 please have a look at this

@asturur
Copy link
Member

asturur commented Dec 12, 2017

try to do fabric.jsdomImplForWrapper(canvas.lowerCanvasEl)._canvas this should give you an instance of nodeCanvas where you can use .toBuffer.

i created fabric.util.getNodeCanvas(element) so that you can use on what you want, either images or canvases

@feuerste
Copy link

Just tried it. It works!

Unfortunately I ran into Automattic/node-canvas#855 when debugging from within VS Code. Updating node canvas to 2.x alpha gave me another error:
Cannot read property 'imageSmoothingEnabled' of null
Shall I open another issue for this?

@asturur
Copy link
Member

asturur commented Dec 12, 2017

tp update to node canvas 2 you have to patch nodejs. node canvas 2 is in alpha stage i ll wait before using it.

@asturur
Copy link
Member

asturur commented Dec 12, 2017

sorry, you have to patch JSDOM

@feuerste
Copy link

Ok, I see, thanks for all your help!

@pmacca
Copy link

pmacca commented Dec 17, 2017

Just starting to with Fabric + Node and ended up here, after banging my head against the wall trying to follow the intro (part4). Good to see that TypeError: fabric.createCanvasForNode is not a function is actually a valid error - I couldn't work out why I couldn't even find that function in the project source code.

It would be great to get some updated docs. Cheers.

@UnlimitedX
Copy link

Hello, as asturur said new fabric.StaticCanvas(); is solving the issue, nevertheless, it seems that canvas.loadFromJSON isn't working anymore too . Any idea ?
Cheers

@asturur
Copy link
Member

asturur commented Dec 17, 2017

What do you mean but loadFromJSON is not working?

@UnlimitedX
Copy link

I mean TypeError: canvas.loadFromJSON is not a function
http://prntscr.com/holer7
Am I missing something ?

@asturur
Copy link
Member

asturur commented Dec 17, 2017 via email

@UnlimitedX
Copy link

Ok, I previously made a git clone of the repo then built the Fabric using node build.js modules=node then used the files in the dist folder as libs for my project. Damn, I just saw I missed the serialization module.
My bad ! Anyway thanks for replying so quickly

@adtm
Copy link

adtm commented Jun 22, 2018

Please update the documentation

@asturur
Copy link
Member

asturur commented Jun 22, 2018

where is the doc still pointing at createCanvasForNode?

@adtm
Copy link

adtm commented Jun 22, 2018

@w4-hojin
Copy link

w4-hojin commented Jul 4, 2018

const canvas = new fabric.StaticCanvas(null, { width: size, height: size });

@temuri416
Copy link

@asturur

Any hope of updating the node,js example?

This:

var fs = require('fs'),
    fabric = require('fabric').fabric,
    out = fs.createWriteStream(__dirname + '/helloworld.png');

var canvas = fabric.StaticCanvas(200, 200);
var text = new fabric.Text('Hello world', {
  left: 100,
  top: 100,
  fill: '#f55',
  angle: 15
});
canvas.add(text);

var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
  out.write(chunk);
});

gives this error:

      this.initialize.apply(this, arguments);
                      ^

TypeError: Cannot read property 'apply' of undefined

@asturur
Copy link
Member

asturur commented Dec 8, 2018

yes i ll update it now. is the new function but with the old arguments.

@temuri416
Copy link

@asturur

If I may ask... Could you also please clearly list dependencies in one spot, along with the required versions of jsdom, node-canvas, node.js?

That'd be phenomenal.

@asturur
Copy link
Member

asturur commented Dec 8, 2018

Yes.
I ll add in that old page.
I m trying to migrate to node-canvas 2 and latest jsdom anyway.
Anyway npm install, and following node-canvas prerequisites should give you all you need.

@temuri416
Copy link

Great!

I also wanted to say that instead of pointing users to various external links that contain installation instructions, it would be lot easier for us to just have a single npm install that'll do the job :-)

@asturur
Copy link
Member

asturur commented Dec 8, 2018

Sure, but npm-install can't take care of system level deps that will make the node-canvas able to compile correctly.
That is where most of the burden come from

@retainleo
Copy link

Hi @asturur
I've been trying to get fabric on node working with no luck. I'm getting the same error as temuri416.
I appreciate you are very busy, but would you be able to post the current working version numbers of fabric, node-canvas, node etc, the required dependencies and any change to the node.js example code on this thread please?
I'm working to a really tight deadline on a project so this would be really appreciated!
Thank you,
Leo

@asturur
Copy link
Member

asturur commented Dec 13, 2018

on what system, architecure, are you running node?

linux? macos? windows? In case of linux which distro? is it an x86 or x64 machine?

@retainleo
Copy link

Apologies, Windows x64.

@asturur
Copy link
Member

asturur commented Dec 13, 2018

that would be your production environment too?

@retainleo
Copy link

Yes, production is planned to be on our Azure Windows Server 2016 VM. We could also create an Ubuntu VM if needed, but we'd prefer to use our existing Windows VM.

@asturur
Copy link
Member

asturur commented Dec 13, 2018 via email

@retainleo
Copy link

I know you can deploy from github to azure via the azure CLI, would that help?
https://docs.microsoft.com/en-us/azure/app-service/scripts/app-service-cli-deploy-github

@asturur
Copy link
Member

asturur commented Dec 13, 2018 via email

@retainleo
Copy link

Azure do have Azure Pipelines which is free for open source projects: https://github.com/marketplace/azure-pipelines could this be the solution?

@temuri416
Copy link

@asturur

Could you please tell us, at this moment, which versions of jsdom, node-canvas and node.js are supported/required by fabric.js v2?

It would be nice to have that information in one place :)

Cheers!

@pixamora
Copy link

@asturur

Any hope of updating the node,js example?

This:

var fs = require('fs'),
    fabric = require('fabric').fabric,
    out = fs.createWriteStream(__dirname + '/helloworld.png');

var canvas = fabric.StaticCanvas(200, 200);
var text = new fabric.Text('Hello world', {
  left: 100,
  top: 100,
  fill: '#f55',
  angle: 15
});
canvas.add(text);

var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
  out.write(chunk);
});

gives this error:

      this.initialize.apply(this, arguments);
                      ^

TypeError: Cannot read property 'apply' of undefined

@temuri416 Did you ever figure out how to get rid of that apply of undefined error? I can't seem to get rid of it.

@asturur
Copy link
Member

asturur commented Mar 15, 2019

i updated it, i did not push up the website yet.
The new example is for fabric 3.0 and node-canvas 2.

@litehacker
Copy link

Just starting to with Fabric + Node and ended up here, after banging my head against the wall trying to follow the intro (part4). Good to see that TypeError: fabric.createCanvasForNode is not a function is actually a valid error - I couldn't work out why I couldn't even find that function in the project source code.

It would be great to get some updated docs. Cheers.

#4586 (comment)

@constantank
Copy link

@asturur hi i tried to run the server rendering demo introduced in tutorial
image

and the file was excuted perfectly shows no error , but the out put png has nothing on it.
image
would you please help me out? thank you so much~~~ @asturur

@constantank
Copy link

my node version is -> 13.11.0
node-canvas -> 2.6.1
jsdom -> 16.2.1
fabric -> 3.6.3
@asturur

@asturur
Copy link
Member

asturur commented May 24, 2020

because canvas.add will render before the next screen refresh ( i now is weird under node ). So you have to add a renderAll imperatively by yourself.
The demo should be fixed probably.

canvas.createPNGStream is the internal node-canvas functionality and does not know anything about what objects are on the canvas.

@Wavewash
Copy link

Hi friends,
Just wanted to comment that there still needs to be a canvas.renderAll() added in the hello world test otherwise it doesn't render anything:
http://fabricjs.com/fabric-intro-part-4

var fs = require('fs'),
    fabric = require('fabric').fabric,
    out = fs.createWriteStream(__dirname + '/helloworld.png');

var canvas = new fabric.StaticCanvas(null, { width: 200, height: 200 });
var text = new fabric.Text('Hello world', {
  left: 100,
  top: 100,
  fill: '#f55',
  angle: 15
});
canvas.add(text);
canvas.renderAll(); //added render all

var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
  out.write(chunk);
});

@asturur
Copy link
Member

asturur commented Sep 15, 2020

good point

djmetzle added a commit to iFixit/node-markup that referenced this issue Aug 4, 2022
The Fabric libary now relies entirely on `jsdom`, so the `canvas` is
abstracted away. Use the `StaticCanvas` form, that is the current
recommendation for use with node.

See: fabricjs/fabric.js#3885
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests