Skip to content

Canvas Module

The Canvas Module (@zumito-team/canvas-module) is a low-level utility that wraps node-canvas, gifencoder, and sharp to provide easy canvas rendering, image loading, and animated GIF generation. It is a dependency for other visual modules (like Stickman Fight and DisTube).

Terminal window
npm install @zumito-team/canvas-module

Add to your zumito.config.ts if used directly:

bundles: ['@zumito-team/canvas-module']

The main export is the CanvasUtils class — a high-level wrapper for canvas operations.

import { CanvasUtils } from '@zumito-team/canvas-module';
const canvas = new CanvasUtils({
width: 500,
height: 300,
isGif: false,
delay: 100,
quality: 10,
repeat: 0,
format: 'image/png'
});
MethodSignatureDescription
getContext()(): CanvasRenderingContext2DReturns the 2D rendering context.
getCanvas()(): CanvasReturns the underlying Canvas object.
startEncoder()(): voidStarts the GIF encoder (only in GIF mode).
addFrame()(): voidAdds the current canvas state as a GIF frame.
toAttachment(filename?)(): Promise<AttachmentBuilder>Finishes encoding and returns a Discord attachment.
drawBackground(color1, color2)(c1: string, c2: string): voidDraws a vertical linear gradient background.
drawRect(x, y, w, h, color)(x,y,w,h,color): voidDraws a filled rectangle.
drawText(x, y, font, color, align?)(text,x,y,font,color,align?): voidDraws text on the canvas.
drawParticles(x, y, color?)(x,y,color?): voidDraws 8 golden sparkle particles around (x,y).
loadImage(src) (static)(src: string): Promise<Image>Fetches an image URL, processes with sharp to PNG, returns a canvas Image.
OptionTypeDefaultDescription
widthnumberrequiredCanvas width in pixels.
heightnumberrequiredCanvas height in pixels.
isGifbooleanfalseProduce an animated GIF instead of a static image.
delaynumber100Frame delay in ms (for GIF).
qualitynumber10GIF encoding quality (1-30, lower = smaller file).
repeatnumber0GIF repeat count. 0 = infinite loop.
format'image/png' | 'image/jpeg''image/png'Output format for non-GIF canvases.
const canvas = new CanvasUtils({ width: 400, height: 200 });
canvas.drawBackground('#1a1a2e', '#16213e');
canvas.drawText('Hello World', 200, 100, 'bold 24px Arial', '#ffffff', 'center');
const attachment = await canvas.toAttachment('hello.png');
await channel.send({ files: [attachment] });
const canvas = new CanvasUtils({
width: 400,
height: 200,
isGif: true,
delay: 50,
quality: 10,
repeat: 0 // infinite loop
});
canvas.startEncoder();
for (let i = 0; i < 20; i++) {
canvas.drawBackground('#1a1a2e', '#16213e');
canvas.drawText(`Frame ${i + 1}`, 200, 100 + i * 2, 'bold 24px Arial', '#ffffff', 'center');
canvas.addFrame();
}
const attachment = await canvas.toAttachment('animation.gif');
await channel.send({ files: [attachment] });
const avatar = await CanvasUtils.loadImage('https://cdn.discordapp.com/avatars/.../avatar.png');
const ctx = canvas.getContext();
ctx.drawImage(avatar, 150, 50, 100, 100);

CanvasUtils is designed as a utility class. There is no service container registration — you instantiate it directly in your own code. Any module can use it for custom rendering:

import { CanvasUtils } from '@zumito-team/canvas-module';
class MyVisualModule extends Module {
async generateCard(user: User): Promise<AttachmentBuilder> {
const canvas = new CanvasUtils({ width: 600, height: 400 });
const avatar = await CanvasUtils.loadImage(user.displayAvatarURL());
canvas.drawBackground('#2c2f33', '#23272a');
canvas.getContext().drawImage(avatar, 50, 50, 100, 100);
canvas.drawText(user.username, 180, 100, 'bold 20px Arial', '#ffffff', 'left');
return canvas.toAttachment('card.png');
}
}
  • canvas — Node.js Canvas implementation.
  • gifencoder — GIF encoding library.
  • sharp — High-performance image processing.
  • zumito-framework
  • Stickman Fight — Uses CanvasUtils for animated fight GIFs.
  • DisTube — Uses CanvasUtils for “now playing” image cards.