Skip to main content

Canvas API

Gurted features a 2D canvas API similar to HTML5 Canvas, plus shader support.

Context

local canvas = gurt.select('#my-canvas')

local ctx = canvas:withContext('2d')
local shaderCtx = canvas:withContext('shader')

2D Drawing Context

Rectangle

-- Fill a solid rectangle
ctx:fillRect(x, y, width, height, color)
ctx:fillRect(50, 50, 100, 75, '#ff0000') -- Red filled rectangle

-- Draw rectangle outline
ctx:strokeRect(x, y, width, height, color, strokeWidth)
ctx:strokeRect(200, 50, 100, 75, '#00ff00', 3) -- Green outline, 3px thick

-- Clear a rectangular area
ctx:clearRect(x, y, width, height)
ctx:clearRect(80, 80, 40, 40) -- Clear 40x40 area

Circle

-- Draw filled or outlined circles
ctx:drawCircle(x, y, radius, color, filled)
ctx:drawCircle(150, 100, 30, '#0000ff', true) -- Filled blue circle
ctx:drawCircle(200, 100, 30, '#ff00ff', false) -- Outlined magenta circle

Text

ctx:drawText(x, y, text, color)
ctx:drawText(20, 250, 'Hello Canvas!', '#ffffff')
ctx:drawText(20, 280, 'Default Font Only', '#ffff00')

-- Font size can be set with setFont (size only, not family)
ctx:setFont('20px sans-serif') -- Only size matters
ctx:drawText(20, 300, 'Larger text', '#00ff00')

local metrics = ctx:measureText('Sample Text')
local textWidth = metrics.width

Path-Based Drawing

For complex shapes, use path-based drawing methods:

ctx:beginPath()

-- Move to starting point without drawing
ctx:moveTo(100, 100)

-- Draw line to point
ctx:lineTo(200, 150)
ctx:lineTo(150, 200)
ctx:lineTo(50, 200)

-- Close the path (connects back to start)
ctx:closePath()

-- Draw the path
ctx:stroke() -- Draw outline
-- or
ctx:fill() -- Fill the shape

Advanced Path Methods

Arc and Circle Paths

-- Draw arc (part of circle)
ctx:arc(x, y, radius, startAngle, endAngle, counterclockwise)

-- Example: Draw a quarter circle
ctx:beginPath()
ctx:arc(200, 200, 50, 0, math.pi/2, false) -- 0 to 90 degrees
ctx:stroke()

-- Full circle path
ctx:beginPath()
ctx:arc(300, 200, 40, 0, 2 * math.pi, false) -- 0 to 360 degrees
ctx:fill()

Curve Methods

-- Quadratic curve (one control point)
ctx:quadraticCurveTo(controlX, controlY, endX, endY)

-- Example: Smooth curve
ctx:beginPath()
ctx:moveTo(50, 300)
ctx:quadraticCurveTo(150, 250, 250, 300) -- Control point at (150,250)
ctx:stroke()

-- Bezier curve (two control points)
ctx:bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endX, endY)

-- Example: S-curve
ctx:beginPath()
ctx:moveTo(50, 350)
ctx:bezierCurveTo(100, 300, 200, 400, 250, 350)
ctx:stroke()

Styling and Properties

Setting Draw Styles

-- Set stroke (outline) color
ctx:setStrokeStyle('#ff0000') -- Red outline
ctx:setStrokeStyle('rgba(255, 0, 0, 0.5)') -- Semi-transparent red
ctx:setStrokeStyle('red-500') -- Tailwind color names
ctx:setStrokeStyle('blue') -- Named colors

-- Set fill color
ctx:setFillStyle('#00ff00') -- Green fill
ctx:setFillStyle('#33aa88') -- Teal fill
ctx:setFillStyle('slate-800') -- Tailwind colors
ctx:setFillStyle('transparent') -- Named transparent

-- Set line width for strokes
ctx:setLineWidth(5) -- 5 pixel wide lines
ctx:setLineWidth(0.5) -- Thin lines

-- Set font for text (size only, not family)
ctx:setFont('20px sans-serif') -- Only size matters
ctx:setFont('16px Arial') -- Font family ignored
ctx:setFont('14px monospace') -- Uses default font at 14px

Color Support: Canvas color parsing is identical to CSS styling - supports hex colors (#ff0000), RGB/RGBA (rgba(255,0,0,0.5)), Tailwind color names (red-500, slate-800), and basic named colors (red, blue, transparent).

Using Styles in Drawing

-- Set up styles first
ctx:setFillStyle('#ff6b6b')
ctx:setStrokeStyle('#4ecdc4')
ctx:setLineWidth(3)

-- Then draw with those styles
ctx:fillRect(50, 50, 100, 100) -- Uses fill style
ctx:strokeRect(200, 50, 100, 100) -- Uses stroke style and line width

-- Styles persist until changed
ctx:setFillStyle('#45b7d1')
ctx:fillRect(50, 200, 100, 100) -- Now uses blue fill

Transformations

Canvas transformations allow you to modify the coordinate system for drawing operations.

Basic Transformations

ctx:save()
ctx:translate(100, 50)
ctx:rotate(math.pi / 4)
ctx:scale(2.0, 1.5)
ctx:fillRect(0, 0, 50, 50)
ctx:restore()
ctx:fillRect(0, 0, 50, 50)

Transformation Examples

ctx:save()
ctx:translate(200, 200)
ctx:rotate(math.pi / 6)
ctx:drawText(-25, 0, 'Rotated', 'Arial', '#000000')
ctx:restore()

for i = 1, 5 do
ctx:save()
ctx:scale(i * 0.3, i * 0.3)
ctx:strokeRect(100, 100, 50, 50)
ctx:restore()
end

for angle = 0, 360, 30 do
ctx:save()
ctx:translate(200, 200)
ctx:rotate(math.rad(angle))
ctx:fillRect(50, -5, 40, 10)
ctx:restore()
end

Shader Context

For advanced visual effects, use the shader context:

local canvas = gurt.select('#shader-canvas')
local shaderCtx = canvas:withContext('shader')

shaderCtx:source([[
shader_type canvas_item;

void fragment() {
vec2 uv = UV;

// Create animated rainbow effect
vec3 color = vec3(
0.5 + 0.5 * cos(TIME + uv.x * 6.0),
0.5 + 0.5 * cos(TIME + uv.y * 6.0 + 2.0),
0.5 + 0.5 * cos(TIME + (uv.x + uv.y) * 6.0 + 4.0)
);

COLOR = vec4(color, 1.0);
}
]])