Skip to content
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

chart.js/HTMLCanvasElement compatibility #100

Closed
jorgecf opened this issue Jul 10, 2020 · 12 comments
Closed

chart.js/HTMLCanvasElement compatibility #100

jorgecf opened this issue Jul 10, 2020 · 12 comments
Milestone

Comments

@jorgecf
Copy link

jorgecf commented Jul 10, 2020

Hi:

I have a little express server where I create some chart.js charts using node-canvas implementation of the canvas API. The thing is, Cairo is a real pain and has a long-standing bug where custom fonts just break in Windows Azure machines... which is what I use.

I tried to switch to this library but with little success. ChartJs contructor takes the following parameters:

constructor(
        context: string | CanvasRenderingContext2D | HTMLCanvasElement | ArrayLike<CanvasRenderingContext2D | HTMLCanvasElement>,
        options: Chart.ChartConfiguration
    );

My try was to just pass the context that I can create via:

var img1 = PImage.make(100,50);
var ctx = img1.getContext('2d');
...
new ChartJS(ctx, options)

but this didn't work since this particular context does not implement CanvasRenderingContext2D.canvas property which is required for chartjs.

What I had done with node-canvas is this:

  const canvas1 = createCanvas(1000, 1000);
    const ctx = canvas1.getContext('2d');
...
 new ChartJS(ctx, options)

It works, since that library actually exposes a CanvasRenderingContext2D.canvas (here) class that implements HTMLCanvasElement methods.

Is there a way to work this out? Maybe it's as easy as just providing a HTMLCanvasElement implementation with already existing methods, and I wouldn't mind patching it myself if this library is kind of compatible already.

Thanks in advance😊😊

@joshmarinacci
Copy link
Owner

Ah yes. the context would need a canvas property that implements the HTMLCanvasElement interface. However, that's a giant interface (because it inherits Element). Do you know what subset of the interface that ChartJS actually uses? Probably width and height, I assume. Anything else?

@jorgecf
Copy link
Author

jorgecf commented Jul 10, 2020

Checking out their last stable release it looks like they use from both Element and HTMLCanvasElement:

  1. width and height as you said
  2. style for width and height as well, and to set the text direction in a restoreTextDirection function
  3. getAttribute (again only to get width and height) and removeAttribute
  4. toDataURL to get the base64

Also getRootNode and getBoundingClientRect, but I'm not pretty sure the function where they're used would be called in this context at all, I'd have to check.

So, as I see, basically width and height related stuff and the base64 stuff that might be realizable via the png stream that is already implemented

@joshmarinacci
Copy link
Owner

It sounds like a fairly easy fix then. Would you like to try implementing it and then I can code review?

@jorgecf
Copy link
Author

jorgecf commented Jul 10, 2020

Sure thing, I'll try to assemble a simple implementation and see what happens

@jorgecf
Copy link
Author

jorgecf commented Jul 10, 2020

I see context.rect() method is not implemented yet, but I'd need it for chartjs. Do you have an idea of an implementation?

@joshmarinacci
Copy link
Owner

for now you could delegate to drawRect or fillRect

@jorgecf
Copy link
Author

jorgecf commented Jul 10, 2020

I forked it and implemented a canvas class and it doesn't fail but does not work either. I tried a two bar chart and the bars seem to be somehow there:

image

I'll try to see if I can fix it furhter in the following days

@joshmarinacci
Copy link
Owner

Probably a transform issue. what's your implementation of 'rect' now?

@jorgecf
Copy link
Author

jorgecf commented Jul 10, 2020

I'm just calling fillrect:

rect(x0, x1, y0, y1) { this.fillRect(x0, y0, x1, y1); }

I probably mixed up the parameters order or now that I'm thinking I might need to apply some colour or something like that

@joshmarinacci
Copy link
Owner

oh yeah, the parameters are wrong. However, that might not be enough to fix it. It could be that fill() is being called as part of a beginPath() / close() sequence and it's using the wrong transform.

@minimusubi
Copy link
Contributor

I'm not entirely familiar with the implementation of the library as I'm still reading through it, but if I'm not wrong, couldn't you implement the rect() function by simply calling moveTo() on the first corner, and then calling lineTo() for each edge?

@joshmarinacci joshmarinacci added this to the vacation milestone Aug 15, 2020
joshmarinacci added a commit that referenced this issue Aug 20, 2020
@joshmarinacci
Copy link
Owner

I just fixed this. Could you test the latest version: 0.2.5

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

3 participants