0

I am trying to replicate some client-side code, using firebase functions. Basically, I am just trying to take a user image, create a circular version of it with a color around it.

Here is the code that I am currently using, which works on the client side of things, but not in Firebase Functions.

export async function createCanvasImage(userImage) {
console.log('createCanvasImage started...');

const canvas = new Canvas(60, 60);
const context = canvas.getContext('2d');

// Creates the blue user image.
async function blueCanvas() {
return new Promise((resolve, reject) => {
  context.strokeStyle = '#488aff';

  context.beginPath();
  context.arc(30, 30, 28, 0, 2 * Math.PI);
  context.imageSmoothingEnabled = false;

  context.lineWidth = 3;
  context.stroke();

  context.imageSmoothingEnabled = false;
  console.log('Canvas Image loaded!');
  context.save();
  context.beginPath();
  context.arc(30, 30, 28, 0, Math.PI * 2, true);
  context.closePath();
  context.clip();
  context.drawImage(userImage, 0, 0, 60, 60);

  context.beginPath();
  context.arc(0, 0, 28, 0, Math.PI * 2, true);
  context.clip();
  context.closePath();
  context.restore();
  const dataURL = canvas.toDataURL();
  console.log(dataURL);
  resolve(dataURL);
  });

}

But it is, unfortunately, returning the following error:

Error creating one of the canvas images... TypeError: Image or Canvas expected

I suspect it's because the image isn't loading properly, but I'm not exactly sure how to get it to load on the server properly.

I was trying to use some code that is provided in the firebase function samples:

 return mkdirp(tempLocalDir)
.then(() => {
// Download file from bucket.
return bucket.file(filePath)
.download({ destination: tempLocalFile });
})
.then(() => {
console.log('The file has been downloaded to', tempLocalFile);
createCanvasImage(tempLocalFile)
.catch(err => {console.log(err); });
})
.catch(err => { console.log(err); });
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jordan Benge
  • 1,053
  • 1
  • 13
  • 30

2 Answers2

1

I think you'll be missing the DOM, unless you're importing libraries that aren't shown here. This is the same reason Nodejs doesn't have a window or document object. There is a good Q&A here Why doesn't node.js have a native DOM?

There is a node canvas implementation node-canvas which can include in your package.

Lex
  • 4,749
  • 3
  • 45
  • 66
0

If you weren't missing the DOM as Lex suggested, I found this and this post where the issue was the node-canvas version.

I only see Canvas in one module but if you were using more, read the explanation below I found here:

I can't find the other issue that discusses this more, but there is no way to fix this in node-canvas itself because it's a limitation of native addons (two different builds of node-canvas don't produce compatible objects). At some level, your JS code needs to make sure that it's using the same node-canvas everywhere. Without knowing anything about your application, this may mean using npm v3 or later, which has a flat(ter) node_modules directory; ensuring that everything that depends on node-canvas is allowed to use the same version; and/or providing a central wrapper for node-canvas that you require instead of requiring node-canvas directly. The first two should hopefully Just Work and not require code changes, but may be brittle.

Rubén C.
  • 1,098
  • 6
  • 16