NAME

Chandra::Canvas - 2D graphics for Chandra applications

SYNOPSIS

use Chandra::App;
use Chandra::Canvas;

my $app = Chandra::App->new(title => 'Canvas Demo');
my $canvas = Chandra::Canvas->new({
    width  => 800,
    height => 600,
    id     => 'gameCanvas',
});

# Draw shapes
$canvas->fill_style('#ff0000')
       ->fill_rect(100, 100, 50, 50)
       ->fill_style('#00ff00')
       ->fill_circle(200, 200, 30)
       ->flush;

$app->run;

DESCRIPTION

Chandra::Canvas provides a hardware-accelerated 2D graphics API for building games and interactive applications. It wraps the HTML5 Canvas API through Chandra's webview backend, with XS-accelerated command batching for optimal performance.

All drawing methods return $self for method chaining.

CONSTRUCTOR

new(\%options)

Create a new canvas instance.

my $canvas = Chandra::Canvas->new({
    width  => 800,      # Canvas width in pixels (default: 800)
    height => 600,      # Canvas height in pixels (default: 600)
    id     => 'myCanvas', # Element ID (auto-generated if not provided)
    style  => 'border: 1px solid black',  # Optional CSS style
    class  => 'game-canvas',              # Optional CSS class
});

ACCESSORS

width()

my $w = $canvas->width;
$canvas->width(1024);

Get or set the canvas width.

height()

my $h = $canvas->height;
$canvas->height(768);

Get or set the canvas height.

id()

my $id = $canvas->id;

Get the canvas element ID.

STYLE METHODS

fill_style($color)

Set the fill color for subsequent fill operations.

$canvas->fill_style('#ff0000');       # Hex color
$canvas->fill_style('rgb(255,0,0)');  # RGB
$canvas->fill_style('rgba(255,0,0,0.5)'); # RGBA

stroke_style($color)

Set the stroke color for subsequent stroke operations.

$canvas->stroke_style('#0000ff');

line_width($width)

Set the line width for stroke operations.

$canvas->line_width(2);

line_cap($style)

Set the line cap style: 'butt', 'round', or 'square'.

$canvas->line_cap('round');

line_join($style)

Set the line join style: 'miter', 'round', or 'bevel'.

$canvas->line_join('round');

miter_limit($limit)

Set the miter limit ratio for line joins.

$canvas->miter_limit(10);

global_alpha($alpha)

Set global transparency (0.0 - 1.0).

$canvas->global_alpha(0.5);

global_composite_operation($operation)

Set the compositing operation. Common values:

'source-over'      # Default, draw over existing
'source-atop'      # Draw only where overlapping
'destination-over' # Draw behind existing
'lighter'          # Additive blending
'xor'              # XOR blend mode

$canvas->global_composite_operation('lighter');

DRAWING METHODS

clear()

Clear the entire canvas.

$canvas->clear;

fill_rect($x, $y, $width, $height)

Draw a filled rectangle.

$canvas->fill_rect(10, 10, 100, 50);

stroke_rect($x, $y, $width, $height)

Draw a rectangle outline.

$canvas->stroke_rect(10, 10, 100, 50);

clear_rect($x, $y, $width, $height)

Clear a rectangular area.

$canvas->clear_rect(10, 10, 100, 50);

fill_circle($x, $y, $radius)

Draw a filled circle.

$canvas->fill_circle(100, 100, 50);

stroke_circle($x, $y, $radius)

Draw a circle outline.

$canvas->stroke_circle(100, 100, 50);

PATH METHODS

begin_path()

Start a new path.

$canvas->begin_path;

close_path()

Close the current subpath.

$canvas->close_path;

move_to($x, $y)

Move the pen to a new position without drawing.

$canvas->move_to(50, 50);

line_to($x, $y)

Draw a line from the current position to the specified point.

$canvas->line_to(150, 150);

arc($x, $y, $radius, $start_angle, $end_angle, $counterclockwise)

Draw an arc.

$canvas->arc(100, 100, 50, 0, 3.14159);

arc_to($x1, $y1, $x2, $y2, $radius)

Draw an arc connected to the previous point with tangent lines.

$canvas->move_to(50, 50)
       ->arc_to(100, 50, 100, 100, 20);  # Rounded corner

bezier_curve_to($cp1x, $cp1y, $cp2x, $cp2y, $x, $y)

Draw a cubic Bezier curve.

$canvas->move_to(50, 50)
       ->bezier_curve_to(100, 0, 150, 100, 200, 50);

quadratic_curve_to($cpx, $cpy, $x, $y)

Draw a quadratic Bezier curve.

$canvas->move_to(50, 50)
       ->quadratic_curve_to(100, 0, 150, 50);

rect($x, $y, $width, $height)

Add a rectangle to the current path.

$canvas->rect(10, 10, 100, 50);

fill()

Fill the current path.

$canvas->fill;

stroke()

Stroke the current path.

$canvas->stroke;

clip()

Set the current path as the clipping region.

$canvas->begin_path
       ->rect(50, 50, 100, 100)
       ->clip;
# Further drawing is clipped to this region

STATE METHODS

save()

Save the current drawing state (styles, transforms) onto the stack.

$canvas->save;

restore()

Restore the most recently saved drawing state.

$canvas->restore;

TRANSFORM METHODS

translate($x, $y)

Move the canvas origin.

$canvas->translate(100, 100);

rotate($angle)

Rotate the canvas around the origin (angle in radians).

$canvas->rotate(0.785398);  # 45 degrees

scale($x, $y)

Scale the canvas.

$canvas->scale(2, 2);  # Double size

transform($a, $b, $c, $d, $e, $f)

Multiply the current transformation matrix by the given matrix.

# Skew transformation
$canvas->transform(1, 0.5, 0.5, 1, 0, 0);

set_transform($a, $b, $c, $d, $e, $f)

Reset and set the transformation matrix directly.

# Set identity matrix
$canvas->set_transform(1, 0, 0, 1, 0, 0);

reset_transform()

Reset the transformation matrix to identity.

$canvas->reset_transform;

CONVENIENCE METHODS

Helper methods for common drawing operations.

line($x1, $y1, $x2, $y2)

Draw a single line between two points.

$canvas->line(10, 10, 100, 100);

polygon($points)

Draw a polygon outline from an arrayref of [x, y] pairs.

$canvas->polygon([[50, 0], [100, 50], [50, 100], [0, 50]]);  # Diamond

fill_polygon($points)

Fill a polygon from an arrayref of [x, y] pairs.

$canvas->fill_polygon([[50, 0], [100, 50], [50, 100], [0, 50]]);

rounded_rect($x, $y, $width, $height, $radius)

Draw a rounded rectangle outline.

$canvas->rounded_rect(10, 10, 100, 50, 10);

fill_rounded_rect($x, $y, $width, $height, $radius)

Fill a rounded rectangle.

$canvas->fill_rounded_rect(10, 10, 100, 50, 10);

BUFFER METHODS

flush()

Send all buffered drawing commands to the canvas and clear the buffer. Call this once per frame after all drawing is complete.

$canvas->clear
       ->fill_style('#f00')
       ->fill_rect(0, 0, 100, 100)
       ->flush;

render()

Generate the HTML for the canvas element.

my $html = $canvas->render;

PERFORMANCE

Chandra::Canvas uses command batching to minimize JavaScript interop overhead. Drawing commands are buffered in Perl (using XS) and sent as a single batch when flush() is called.

For optimal performance:

  • Call flush() once per frame, not after each draw call

  • Minimize state changes (fill_style, transforms)

  • Use save()/restore() for isolated state changes

SEE ALSO

Chandra, Chandra::App, Chandra::Element

AUTHOR

LNATION <email@lnation.org>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.