CanvasTarget
CanvasTarget is a render target implementation that outputs to an HTML Canvas element in browser environments.
Overview
The CanvasTarget class implements the RenderTarget interface, providing a way to render ASCII characters to a Canvas element with full color support.
Constructor
new CanvasTarget(canvas: HTMLCanvasElement, options: CanvasTargetOptions)Parameters
- canvas: The HTML Canvas element to render to
- options: Configuration (see below)
CanvasTargetOptions
interface CanvasTargetOptions {
width: number; // Width in characters
height: number; // Height in characters
charWidth?: number; // Character width in pixels (default: 8)
charHeight?: number; // Character height in pixels (default: 16)
fontFamily?: string; // Font family (default: 'monospace')
fontSize?: number; // Font size in pixels (default: 14)
}Example Usage
Basic Setup
import { CanvasTarget } from "@shaisrc/tty";
// Get canvas element
const canvas = document.getElementById("game") as HTMLCanvasElement;
// Create target with 80x24 character grid
const target = new CanvasTarget(canvas, { width: 80, height: 24 });
// Canvas size will be 640x384 pixels (80*8 x 24*16)Custom Font Settings
const target = new CanvasTarget(canvas, {
width: 80,
height: 24,
charWidth: 12,
charHeight: 20,
fontFamily: "Courier New",
fontSize: 16,
});
// Canvas size will be 960x480 pixels (80*12 x 24*20)Using with Renderer
import { CanvasTarget } from "@shaisrc/tty";
const canvas = document.getElementById("game") as HTMLCanvasElement;
const target = new CanvasTarget(canvas, { width: 80, height: 24 });
// Draw some characters
target.clear();
target.setCell(0, 0, "@", "yellow", "black");
target.setCell(1, 0, "H", "white", null);
target.setCell(2, 0, "e", "white", null);
target.setCell(3, 0, "l", "white", null);
target.setCell(4, 0, "l", "white", null);
target.setCell(5, 0, "o", "white", null);
target.flush(); // No-op for canvas (updates are immediate)Methods
setCell(x: number, y: number, char: string, fg: Color, bg: Color): void
Sets a character at the specified grid position.
// Draw an 'X' with red foreground and black background
target.setCell(10, 5, "X", "red", "black");
// Draw a space (effectively clearing the cell)
target.setCell(10, 5, " ", null, null);
// Background only (no visible character)
target.setCell(10, 5, " ", null, "blue");Behavior:
- Background is drawn first if provided
- Character is not drawn if it's a space or empty
- Foreground color is used for the character
- Coordinates are in character grid units, not pixels
clear(): void
Clears the entire canvas.
target.clear();This removes all content and resets the canvas to transparent.
flush(): void
Flushes changes to the output (no-op for canvas).
target.flush();Note: Canvas updates are immediate, so this method does nothing. It exists to satisfy the RenderTarget interface.
getSize(): { width: number; height: number }
Returns the size of the render target in characters.
const { width, height } = target.getSize();
console.log(`Grid is ${width}x${height} characters`);getCanvas(): HTMLCanvasElement
Returns the underlying canvas element.
const canvas = target.getCanvas();
console.log(`Canvas size: ${canvas.width}x${canvas.height}px`);setOptions(options: Partial<CanvasTargetOptions>): void
Updates canvas configuration at runtime.
// Make characters larger
target.setOptions({
charWidth: 16,
charHeight: 24,
});
// Change font
target.setOptions({
fontFamily: "Consolas",
fontSize: 18,
});Note: Changing charWidth or charHeight will resize the canvas element.
Coordinate System
CanvasTarget uses a character-based coordinate system:
- Origin (0, 0) is at the top-left
- X increases to the right
- Y increases downward
- All coordinates are in character units, not pixels
(0,0) ─────> X
│
│
│
▼
YPixel positions are calculated automatically:
pixelX = characterX * charWidth;
pixelY = characterY * charHeight;Color Support
CanvasTarget supports all color formats via the color utility functions:
// Named colors
target.setCell(0, 0, "@", "red", "black");
// Hex colors
target.setCell(1, 0, "#", "#ff00ff", "#000000");
// RGB colors
target.setCell(2, 0, "$", { r: 255, g: 128, b: 0 }, null);
// Null for transparent
target.setCell(3, 0, "%", "white", null);Colors are automatically converted to CSS rgb() strings internally.
Performance Considerations
Immediate Rendering
Unlike some render targets, CanvasTarget draws immediately on each setCell() call. This means:
- No buffering delay
- Updates are visible immediately
- No need to call
flush()
Optimization Tips
- Minimize setCell calls: Only update cells that have changed
- Batch operations: Group related drawing operations together
- Use requestAnimationFrame: For smooth animations
- Clear selectively: Only clear areas that need updating
Example of efficient rendering:
function render() {
// Only clear and redraw changed regions
for (const entity of movedEntities) {
target.setCell(entity.oldX, entity.oldY, " ", null, null);
target.setCell(entity.x, entity.y, entity.char, entity.color, null);
}
movedEntities.clear();
requestAnimationFrame(render);
}Browser Compatibility
CanvasTarget requires:
- HTML5 Canvas support
- 2D rendering context
Supported in all modern browsers:
- Chrome/Edge (all versions)
- Firefox (all versions)
- Safari (all versions)
Error Handling
Context Unavailable
const canvas = document.getElementById("game") as HTMLCanvasElement;
try {
const target = new CanvasTarget(canvas, { width: 80, height: 24 });
} catch (error) {
console.error("Failed to create CanvasTarget:", error);
// Error: "Failed to get 2D context from canvas"
}This can happen if:
- Canvas element is invalid
- Another library has acquired the context
- Browser doesn't support 2D context
Complete Example
<!DOCTYPE html>
<html>
<head>
<title>CanvasTarget Example</title>
<style>
body {
margin: 0;
padding: 20px;
background: #1a1a1a;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
canvas {
border: 2px solid #444;
image-rendering: pixelated;
}
</style>
</head>
<body>
<canvas id="game"></canvas>
<script type="module">
import { CanvasTarget } from '@shaisrc/tty';
const canvas = document.getElementById('game');
const target = new CanvasTarget(canvas, {
width: 80,
height: 24,
charWidth: 10,
charHeight: 18,
fontFamily: 'monospace',
fontSize: 14
});
// Draw a simple scene
target.clear();
// Title
const title = "HELLO CANVAS!";
const startX = Math.floor((80 - title.length) / 2);
for (let i = 0; i < title.length; i++) {
target.setCell(startX + i, 2, title[i], 'yellow', 'blue');
}
// Border
for (let x = 0; x < 80; x++) {
target.setCell(x, 0, '═', 'cyan', null);
target.setCell(x, 23, '═', 'cyan', null);
}
for (let y = 0; y < 24; y++) {
target.setCell(0, y, '║', 'cyan', null);
target.setCell(79, y, '║', 'cyan', null);
}
// Player
target.setCell(40, 12, '@', 'white', null);
</script>
</body>
</html>Next Steps
- See Core Types for color and type definitions
- See Color Utilities for color manipulation
- See Renderer API for the high-level rendering interface
