Skip to main content

Paint Primitives

Paint primitives are leaf elements placed inside <ec-canvas-background> or <ec-canvas-overlay> zones. They compile to native LVGL canvas draw actions.

All numeric props accept reactive values — when the underlying state changes, the canvas redraws automatically.

ec-rect

Draws a filled and/or stroked rectangle.

<ec-rect
x={0}
y={0}
width={200}
height={100}
fill="#1a1a2e"
stroke="#333366"
strokeWidth={2}
radius={12}
opacity={255}
/>

Props

PropTypeDefaultDescription
xReactive<number>0Horizontal position in pixels
yReactive<number>0Vertical position in pixels
widthReactive<number>0Width in pixels
heightReactive<number>0Height in pixels
radiusReactive<number>0Corner radius in pixels
fillReactive<string>Fill color as hex string (e.g. "#4caf50")
strokeReactive<string>Stroke (border) color as hex string
strokeWidthReactive<number>1Stroke width in pixels
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_rectangle.

ec-line

Draws a line between two points.

<ec-line
x1={16}
y1={80}
x2={264}
y2={80}
stroke="#333366"
strokeWidth={1}
/>

Props

PropTypeDefaultDescription
x1Reactive<number>0Start X position in pixels
y1Reactive<number>0Start Y position in pixels
x2Reactive<number>0End X position in pixels
y2Reactive<number>0End Y position in pixels
strokeReactive<string>Line color as hex string
strokeWidthReactive<number>1Line width in pixels
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_line.

ec-arc

Draws a circular arc or ring segment. Useful for gauges, progress rings, and circular indicators.

<ec-arc
cx={60}
cy={60}
radius={50}
startAngle={135}
endAngle={315}
stroke="#00e676"
strokeWidth={6}
rounded
/>

Props

PropTypeDefaultDescription
cxReactive<number>0Center X position in pixels
cyReactive<number>0Center Y position in pixels
radiusReactive<number>0Arc radius in pixels
startAngleReactive<number>0Start angle in degrees (0 = 3 o'clock, clockwise)
endAngleReactive<number>360End angle in degrees (0–360)
strokeReactive<string>Arc color as hex string
strokeWidthReactive<number>1Arc line width in pixels
roundedReactive<boolean>Round the arc endpoints
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_arc.

Example: gauge ring

<ec-canvas style={{ width: 120, height: 120 }}>
<ec-canvas-background>
{/* Background track */}
<ec-arc cx={60} cy={60} radius={50} startAngle={135} endAngle={315} stroke="#555577" strokeWidth={6} />
{/* Active fill */}
<ec-arc cx={60} cy={60} radius={50} startAngle={135} endAngle={270} stroke="#00e676" strokeWidth={6} rounded />
</ec-canvas-background>
</ec-canvas>

ec-polygon

Draws a filled polygon with an arbitrary number of vertices.

<ec-polygon
points={[{ x: 40, y: 5 }, { x: 75, y: 70 }, { x: 5, y: 70 }]}
fill="#ff9800"
stroke="#ffffff"
strokeWidth={2}
/>

Props

PropTypeDefaultDescription
pointsArray<{ x: number; y: number }>Ordered list of polygon vertices
fillReactive<string>Fill color as hex string
strokeReactive<string>Border color as hex string
strokeWidthReactive<number>1Border width in pixels
radiusReactive<number>0Corner radius in pixels
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_polygon.

Example: triangle indicator

<ec-canvas style={{ width: 80, height: 80 }}>
<ec-canvas-background>
<ec-polygon
points={[{ x: 40, y: 5 }, { x: 75, y: 70 }, { x: 5, y: 70 }]}
fill="#ff9800"
stroke="#ffffff"
strokeWidth={2}
/>
</ec-canvas-background>
</ec-canvas>

ec-text

Draws pixel-positioned text on the canvas. Use this for text that needs precise placement outside normal LVGL widget flow — labels at specific coordinates, annotations, or HUD-style overlays.

<ec-text
x={4}
y={4}
text="Pixel text"
fill="#e0e0e0"
maxWidth={192}
textAlign="center"
/>

Props

PropTypeDefaultDescription
xReactive<number>0Horizontal position in pixels
yReactive<number>0Vertical position in pixels
textReactive<string>Text content
fontReactive<string>Font reference (e.g. from useFont())
fillReactive<string>Text color as hex string
maxWidthReactive<number>0Maximum text width before wrapping (px)
textAlignReactive<string>Text alignment: "left", "center", or "right"
letterSpacingReactive<number>Letter spacing in pixels
lineSpacingReactive<number>Line spacing in pixels
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_text.

tip

For interactive or styled text, prefer <lvgl-label> inside <ec-canvas-content>. Use <ec-text> only when you need pixel-precise placement that bypasses LVGL layout.

ec-image

Draws an image on the canvas with optional transforms (rotation, scale, skew).

const icon = useImage({ file: './assets/icon.png', type: 'RGBA', resize: '32x32' });

<ec-image
x={10}
y={10}
src={icon}
rotation={900}
scale={512}
/>

Props

PropTypeDefaultDescription
xReactive<number>0Horizontal position in pixels
yReactive<number>0Vertical position in pixels
srcReactive<string>Image source (e.g. from useImage())
rotationReactive<number>Rotation angle (degrees × 10, e.g. 900 = 90°)
scaleReactive<number>Uniform scale factor (256 = 1×)
scaleXReactive<number>Horizontal scale factor (256 = 1×)
scaleYReactive<number>Vertical scale factor (256 = 1×)
skewXReactive<number>Horizontal skew (degrees × 10)
skewYReactive<number>Vertical skew (degrees × 10)
pivotXReactive<number>0Transform origin X in pixels
pivotYReactive<number>0Transform origin Y in pixels
opacityReactive<number>Opacity: 0–255 integer or 0.0–1.0 float

Compiles to lvgl.canvas.draw_image.

Reactive paint props

Any numeric or color prop can accept a reactive value. When the bound state changes, the compiler generates C++ code to redraw the affected primitive:

const temperature = useHAEntity('sensor.temperature');

<ec-canvas style={{ width: 48, height: 48 }}>
<ec-canvas-background>
<ec-rect
x={0} y={0} width={48} height={48}
fill={temperature.state}
radius={24}
/>
</ec-canvas-background>
</ec-canvas>