Overview
The Perspective XY Chart component in Inductive Automation's Ignition platform provides a flexible way to display either time-series or XY data on a configured view. When a series is added without an explicit line color, the property editor displays a default gray swatch while the rendered chart uses a color chosen by the underlying charting library. This visual mismatch between the property UI and the rendered line causes confusion during commissioning and is the most common misinterpretation of the series.#.line.appearance.stroke.color property.
This reference documents the exact behavior, the underlying mechanism, the recommended configuration workflow, and the verification checks required to make the property editor reflect the actual rendered line color. All paths and property names are taken from the official Ignition 8.1 Perspective user manual. See the Perspective XY Chart documentation and the Inductive University XY Chart training video for the canonical reference set.
Problem Details
When an engineer adds an XY Chart to a Perspective view, configures a series via props.series, and inspects the line appearance sub-property, the following behavior is observed:
- The
series.<index>.line.appearance.stroke.colorproperty displays a default gray swatch (or an empty value) in the property editor. - The rendered line on the chart uses a different color (blue, green, red, etc.) chosen automatically by the charting library.
- Editing the color value in the property editor updates the rendered line correctly, but reverting to the default gray does not restore the auto-picked color — the line is rendered with no visible color or the next palette entry.
The mismatch is not a bug in the property binding pipeline; it is a deliberate delegation of color selection to the charting engine when the user has not specified a value. The property name (stroke.color) is intuitively correct, but the default state does not reflect what is actually being drawn on the canvas.
Root Cause
The Perspective XY Chart delegates initial color selection to the third-party charting library it embeds. The library is responsible for:
- Ensuring that no two series in the same chart use the same color.
- Ensuring adequate contrast between adjacent series for legibility.
- Avoiding colors that conflict with the active theme background or axis chrome.
To satisfy these constraints without writing back to the property tree on every render, the library reads the property as a hint, applies its own palette when the hint is empty or equal to the default placeholder, and uses the hint directly when the user provides a non-default value. The placeholder gray in the property editor is therefore not a color value; it is a visual indicator that the property is unset.
Prerequisites
Before configuring line colors, confirm the following:
- Ignition 8.1.x gateway with the Perspective module licensed and active.
- A Perspective project loaded in the Designer with a view open for editing.
- An XY Chart component dropped onto the view from the Component Palette (Chart category → XY).
- At least one data source configured and bound to
props.dataSources. Time-series sources should return tag history data; XY sources should return paired numeric arrays. - Read access to the Perspective XY Chart user manual page for the canonical property tree.
Step-by-Step Resolution
Follow the steps below to make the rendered line color match the property editor value and to lock the color so it does not change when additional series are added.
Step 1 — Add the XY Chart Component
- In the Designer, open the target view.
- From the Component Palette, select the Chart category.
- Drag the XY component onto the view canvas.
- Resize and position the chart as required for the layout.
Step 2 — Configure the Data Source
- Select the chart component on the canvas.
- In the Property Editor, expand
props→dataSources. - Add a new data source object. The minimum structure is:
{ "key": "series1", "type": "taghistorian", "tagPath": "[default]Path/To/Tag" } - For XY data, set
typeto"xy"and provide pairedxandyarrays or a query binding that returns them.
Step 3 — Add a Series Entry
- Expand
props.seriesin the Property Editor. - Add a new series object. The minimum structure is:
{ "name": "Series 1", "dataSource": "series1", "line": { "appearance": { "stroke": { "color": "", "width": 1 } } } } - Note that the
colorfield is intentionally left as an empty string. This is the value that triggers the auto-pick behavior.
Step 4 — Set an Explicit Color
- In the Property Editor, locate
series.0.line.appearance.stroke.color. - Click the color swatch and choose an explicit value (hex, RGB, or named CSS color). For example:
"#1f77b4". - Confirm in the Designer preview that the rendered line now matches the selected color.
Step 5 — Bind the Color (Optional)
To make the color dynamic, bind series.0.line.appearance.stroke.color to a tag, a parameter, or an expression. Recommended expression patterns:
if({[default]Line/OverrideColor} <> "",
{[default]Line/OverrideColor},
"#1f77b4")
This binding returns the operator override when present, otherwise falls back to the explicit color. Avoid binding to an empty string unless you intend to re-enable the auto-pick behavior.
Step 6 — Repeat for Additional Series
When adding series 1, 2, 3, etc., assign each a distinct explicit color to prevent the library from re-picking and to make the property editor and the canvas agree. A safe starting palette is shown in the table below.
Recommended Starting Palette
| Series Index | Hex | Common Name | Contrast on Light Theme | Contrast on Dark Theme |
|---|---|---|---|---|
| 0 | #1f77b4 | Tableau Blue | Good | Good |
| 1 | #ff7f0e | Tableau Orange | Good | Good |
| 2 | #2ca02c | Tableau Green | Good | Good |
| 3 | #d62728 | Tableau Red | Good | Good |
| 4 | #9467bd | Tableau Purple | Good | Good |
| 5 | #8c564b | Tableau Brown | Good | Good |
| 6 | #e377c2 | Tableau Pink | Good | Good |
| 7 | #7f7f7f | Tableau Gray | Marginal | Good |
Property Reference
The full property tree for the line appearance is:
series.<index>.line.appearance.stroke.color (string, CSS color)
series.<index>.line.appearance.stroke.width (number, pixels)
series.<index>.line.appearance.stroke.dash (array, pixel pattern)
series.<index>.line.appearance.shape (object, marker config)
series.<index>.line.appearance.fill (object, area fill config)
Only the color field is delegated to the library when empty. width, dash, shape, and fill always reflect their explicit values because the library does not auto-pick them.
Data Source Configuration
The XY Chart supports three data source shapes:
-
Time-series (tag historian): The library maps the timestamp domain to the X axis and the value to the Y axis.
typemust be"taghistorian". -
XY pairs (database or expression): The library maps explicit X and Y arrays to the axes.
typemust be"xy"and the payload must containxandynumeric arrays of equal length. -
Custom (function-bound JSON): The component accepts any payload that the library can interpret.
typeis set to"custom"and a binding supplies the data.
The data source type does not affect color behavior. The library applies the same auto-pick logic to all three shapes.
Charting Library Behavior
The embedded charting library maintains an internal palette index that increments each time a new series is added without an explicit color. The index wraps at the palette length (typically eight colors) and resets when the chart is re-rendered from a new data set. The auto-picked color is not deterministic across re-renders unless the series order is stable. To guarantee a specific color for a specific series, always set color to an explicit value.
color empty, the library will assign them different colors on the first render, but the assignment depends on the order in which the series are processed. Re-ordering the series in props.series will swap the auto-picked colors. This is the most common cause of "the line color changed after I added a new series" reports.
Theme Considerations
The auto-picked palette is tuned for the default light theme. On the dark theme, the lower-order palette entries (especially gray) may have insufficient contrast against the canvas. Set explicit colors when the project is deployed against a dark theme to avoid legibility regressions.
To apply a project-wide palette, bind each series.<i>.line.appearance.stroke.color to a property of a custom property sheet (for example, params.chartColors) and let the view pass a single array down to all charts. This keeps the palette in one location and prevents drift between views.
Verification
After configuring explicit colors, validate the result with the following checks:
- Open the view in the Designer and confirm the rendered line color matches the swatch in the Property Editor.
- Open a web browser session pointed at the same project and confirm the same color renders. The library applies the same palette to both Designer and client.
- Add a second series with an empty
colorand confirm the first series retains its explicit color while the second receives an auto-picked color from the remaining palette entries. - Bind a tag to
colorand change the tag value at runtime. The line should update within one render cycle (typically under 200 ms on a local client).
Troubleshooting Matrix
| Symptom | Likely Cause | Remediation |
|---|---|---|
| Property shows gray, line shows a different color | Auto-pick delegation | Set an explicit color value |
| Line color changes after adding a new series | Auto-pick re-ordering | Set explicit colors on all series |
| Line is invisible against the canvas | Auto-picked gray on dark theme | Set an explicit high-contrast color |
| Color binding does not update at runtime | Binding evaluates to empty string | Ensure the binding always returns a non-empty string; use a fallback expression |
| Designer preview differs from client | Stale browser cache | Hard-reload the client (Ctrl+F5) |
| Color flicker on initial render | Library re-palette after data arrives | Pre-assign explicit colors before binding data |
| Color not applied when series added dynamically | New series inherited empty color | Bind new series entries to a color from the project palette |
Best Practices
- Always set explicit colors for production screens. Reserve auto-pick for prototypes and ad-hoc debugging.
- Centralize the palette in a project parameter or a UDT instance to keep colors consistent across views.
- Document the palette assignment in a property sheet comment so that future engineers know which color belongs to which series.
- Avoid binding
colorto an expression that can return an empty string unless the auto-pick behavior is desired. - For accessibility, ensure the chosen palette passes WCAG 2.1 AA contrast (3:1 for non-text graphical objects) against both light and dark themes.
FAQ
Why does the line color property show gray in the Property Editor but a different color on the chart?
The gray swatch is a placeholder indicating the property is unset. When the value is empty, the embedded charting library auto-picks a color from its internal palette to satisfy contrast and uniqueness constraints. Set an explicit value in series.<index>.line.appearance.stroke.color to make the property editor and the rendered line agree.
How do I make the line color dynamic at runtime?
Bind series.<index>.line.appearance.stroke.color to a tag, parameter, or expression. Use a fallback expression such as if({tag} <> "", {tag}, "#1f77b4") to guarantee a non-empty value and prevent the library from re-entering auto-pick mode.
Can I lock the palette so all charts in the project use the same color order?
Yes. Define a project parameter (for example, params.chartPalette) as a string array and bind each series.<i>.line.appearance.stroke.color to {params.chartPalette}[i]. This keeps the assignment deterministic across all views and survives chart re-ordering.
Does the data source type affect color behavior?
No. The auto-pick logic is independent of the data source shape (tag historian, XY pairs, or custom). Color behavior is controlled solely by the value of series.<index>.line.appearance.stroke.color.
Why does the line color change when I add a new series?
When multiple series leave color empty, the library assigns palette entries in the order the series are processed. Adding a new series can shift the assignment of existing series if the internal palette index wraps. Set explicit colors on all series to prevent this shift.