Advanced Graphics (Compositions)
Advanced Graphics, internally called ImageComposition, is a powerful system for creating custom display graphics on panel screens. While simple icon or widget feedback covers most use cases, compositions allow you to build complex, layered graphics with dynamic text, conditional visibility, and precise positioning.
When to Use Compositions
Use the Composition data source when you need:
- Multiple elements on a single display (text + icons + shapes)
- Dynamic text with IO references showing real-time values
- Conditional rendering where elements appear/hide based on system state
- Custom layouts with precise positioning and alignment
- Status dashboards combining multiple data sources
For simple cases, stick with the standard Icon, Widget, or IOref data sources.
Enabling Composition Mode
To use compositions, set the Graphic Source field to Composition in the Display Graphics feedback handler. This reveals the Composition configuration section.
Composition Types
Each composition has a Type that determines what it renders. The most common is Layers for complex graphics, but you can also use simpler types directly.
Layers
The container type for building complex graphics. A Layers composition holds an array of child compositions that are rendered in order (first in array = bottom layer, last = top).
{
"Type": "Layers",
"Layers": [
{ /* bottom layer */ },
{ /* middle layer */ },
{ /* top layer */ }
]
}
Graphics
Draw vector shapes and TrueType text. Supports rectangles, ellipses, lines, pixels, and text with advanced styling.
{
"Type": "Graphics",
"Graphics": [
{
"Type": "Rectangle",
"ColorCode": "#336699",
"RoundedCorner": 3
},
{
"Type": "Text",
"Text": "Camera 1",
"TextFont": "Small",
"ColorCode": "WHITE"
}
]
}
Image
Display icons, QR codes, or images from IO references.
MonoText
Pixel-style text using classic SKAARHOJ OLED fonts. Best for simple labels on monochrome or small displays.
MonoRect
Simple filled or outlined rectangles. Useful for title bars or frames.
Widget
Embed VU meters or strength indicators. See Display Widgets for details.
The Box Model (Positioning)
Every composition has a Box that defines its canvas size and position within the parent. Understanding the box model is essential for creating well-positioned graphics.
Size (Width / Height)
| Value | Behavior |
|---|---|
0 (default) | Use full parent dimension |
Positive (e.g., 50) | Exact size in pixels |
Negative (e.g., -10) | Parent size minus this value (creates margins) |
Example: Width: -10 on a 128px parent = 118px canvas with 5px margin on each side.
Alignment
Vertical Align: Top, Center (default), Bottom
Horizontal Align: Left, Center (default), Right
Offset
OffsetX and OffsetY add pixel adjustments after alignment. Use for fine-tuning position.
Canvas Rotation
Rotate the entire canvas before rendering:
- Empty = no rotation
CW= 90 degrees clockwiseCCW= 90 degrees counter-clockwise180= upside down
Fitting (Scaling)
How the composition scales to fit its destination:
1:1= no scaling (default)Fit= scale to fit inside, preserve aspect ratioFill= scale to fill, preserve aspect ratio (may crop)Stretch= scale to fill, ignore aspect ratio
Graphics Elements
When using Type: "Graphics", you define an array of graphic elements. Each element has its own type and styling options.
Element Types
| Type | Description |
|---|---|
Rectangle | Filled or outlined box with optional rounded corners |
Ellipse | Filled or outlined circle or oval |
Line | Straight line between two points |
Pixel | Single colored pixel |
Text | TrueType font text with advanced alignment |
Colors
Colors can be specified as:
- Reactor color names:
RED,GREEN,BLUE,WHITE,BLACK,AMBER,CYAN,DARKGRAY, etc. - HTML hex codes:
#336699or#369 - IO references:
{Device.TallyColor}for dynamic colors
Two color properties are available:
- ColorCode - Fill color for shapes, text color for text
- StrokeColorCode - Outline/border color (shapes only)
Available Fonts
Pixel Fonts (crisp at default sizes):
Small- 8pt, compactPixelArial,PixelArial-Bold- 8ptPixelType- 16pt, monospace-stylem5x7,m3x6- Retro pixel fontsDogicaPixel,DogicaPixel-Bold- 8pt stylizedUnifont- 16pt, excellent Unicode support
TrueType Fonts (smooth, scalable):
NotoSans-Regular,NotoSans-Bold,NotoSans-Italic,NotoSans-BoldItalic
Text Alignment
TextHorizontalAlign: Left, Center (default), Right, CenterLeft
CenterLeft centers text if it fits, otherwise left-aligns to prevent cutoff.
TextVerticalAlign: Top, Center (default), Bottom
Dynamic Content
IO References in Text
Embed dynamic values using curly brace syntax:
{
"Type": "Text",
"Text": "Source: {Device.Input.Name}"
}
Common system references:
{System:ProjectTitle}- Current project name{System:ConfigTitle}- Current configuration name{System:UptimeFormatted}- System uptime{System:IPAddress}- System IP address{System:Layers}- Number of active layers{System:HWCs}- Number of hardware components{System:Devices/1:Name}- Name of device at index 1{Panels:Panel/1/Name}- Name of panel at index 1
Conditional Visibility (ActiveIf)
Show or hide entire layers based on conditions:
{
"ActiveIf": "System:Devices:Unconnected == 0",
"Type": "Graphics",
"Graphics": [
{
"Type": "Rectangle",
"ColorCode": "GREEN"
},
{
"Type": "Text",
"Text": "All OK",
"ColorCode": "BLACK"
}
]
}
This layer only renders when all devices are connected. Use standard condition syntax with ==, >, <, &&, || operators.
Case Study: Reactor Activity Configuration
The Blue Pill - Reactor Activity configuration demonstrates advanced composition techniques. It displays a real-time system status dashboard on the Blue Pill's OLED display.
Display Structure
The configuration divides the display into 5 regions:
| Region | Content |
|---|---|
| TopQuarter | Reactor logo icon |
| SecondQuarter | Project name, uptime, layer/HWC counts, config title |
| ThirdQuarter | Panel names and connection status |
| BottomQuarter | Device names and connection status |
| BottomStrip | IP address |
Key Technique: Layered Status Section
The device status section demonstrates combining multiple layers with conditional visibility:
{
"Type": "Layers",
"Layers": [
{
"Box": { "Width": 40, "Height": 8, "VerticalAlign": "Top", "HorizontalAlign": "Left" },
"Type": "Graphics",
"Graphics": [
{ "Type": "Rectangle", "ColorCode": "#cce3f0", "RoundedCorner": 2 },
{ "Type": "Text", "Text": "Devices", "ColorCode": "BLACK", "TextFont": "Small", "OffsetX": 2 }
]
},
{
"Box": { "Width": -45, "HorizontalAlign": "Right" },
"Type": "Graphics",
"Graphics": [
{ "Type": "Text", "Text": "{System:Devices/1:Name}", "ColorCode": "WHITE", "TextFont": "Small", "OffsetY": 1 },
{ "Type": "Text", "Text": "{System:Devices/2:Name}", "ColorCode": "WHITE", "TextFont": "Small", "OffsetY": 9 }
]
},
{
"ActiveIf": "System:Devices:Warnings == 0 && System:Devices:Unconnected == 0",
"Box": { "Width": 40, "Height": 9, "VerticalAlign": "Top", "HorizontalAlign": "Left", "OffsetY": 10 },
"Type": "Graphics",
"Graphics": [
{ "Type": "Rectangle", "ColorCode": "GREEN", "RoundedCorner": 2 },
{ "Type": "Text", "Text": "{System:Devices:Connected} OK", "ColorCode": "BLACK", "TextFont": "Small" }
]
},
{
"ActiveIf": "System:Devices:Unconnected > 0",
"Box": { "Width": 19, "Height": 9, "VerticalAlign": "Top", "HorizontalAlign": "Left", "OffsetX": 21, "OffsetY": 10 },
"Type": "Graphics",
"Graphics": [
{ "Type": "Rectangle", "ColorCode": "RED", "RoundedCorner": 2 },
{ "Type": "Text", "Text": "{System:Devices:Unconnected} !!", "ColorCode": "BLACK", "TextFont": "Small" }
]
}
]
}
What this does:
- Header layer - Light blue rounded rectangle with "Devices" label (always visible)
- Device list layer - Shows device names on the right side
- Green OK indicator - Only shows when all devices are healthy
- Red error indicator - Only shows when devices are disconnected
The ActiveIf conditions create a dynamic status display that automatically updates based on device health.
Tips and Best Practices
Layer Ordering
Layers render from first to last in the array, meaning the first layer is at the bottom. Place background elements first, foreground elements last.
Using Negative Dimensions
Negative width/height values create automatic margins:
Width: -10= 5px margin on left and rightHeight: -4= 2px margin on top and bottom
This is more maintainable than calculating exact sizes.
Debugging Layouts
Enable ShowBox to draw a red border around any composition layer. This helps visualize boundaries during development:
{
"ShowBox": true,
"Type": "Graphics",
"Graphics": [ ... ]
}
Font Selection
- Use pixel fonts (
Small,PixelArial) for small displays or when crisp rendering is important - Use NotoSans fonts when you need scalable, smooth text
Unifontis best for international characters
Performance
Compositions are cached and render at a maximum of 25 frames per second. For rapidly changing data, this is usually sufficient. Avoid extremely complex nested structures if you notice performance issues.
Related Topics
- Feedbacks and Actions - How feedback handlers work
- Display Widgets - VU meters and strength indicators
- Variables and Conditions - Condition syntax for ActiveIf