-
Notifications
You must be signed in to change notification settings - Fork 4
Cookbook A2 Adding a Pie Chart
A combined chart: the stacked area chart from A1 in the lower half, and a pie chart in the upper half showing the total energy share per category for the whole week.
Just as in A1, the chart state remains the master for the chart definition. You will:
- Update the chart state with a new JSON that adds the pie chart structure and adjusts the layout
- Update the script — it now also fills in the weekly totals for the pie slices
The browser URL and the three energy data states stay completely unchanged.
Completed Cookbook A1, Part B — the following must be in place:
- State
0_userdata.0.flexcharts.energy.chart(chart output) - States
0_userdata.0.energy.consumption.household,.wallbox,.heatpump(data) - The update script from A1 Part B running in the JavaScript adapter
Open 0_userdata.0.flexcharts.energy.chart in the Objects editor, replace its value with the JSON below, and save (ack unchecked).
This is the same chart definition as before, with three additions:
-
"grid": { "top": "55%" }— pushes the area chart into the lower half of the page -
"tooltip": { "trigger": "item" }— works for both area chart and pie - A new pie series with placeholder values (
"value": 0) — the script will fill these in
{
"title": { "text": "Weekly Energy Consumption", "left": "center" },
"tooltip": { "trigger": "item" },
"legend": { "data": ["Household", "Wallbox", "Heat pump"], "top": "8%" },
"toolbox": { "feature": { "saveAsImage": {} } },
"grid": { "top": "55%" },
"xAxis": [{ "type": "category", "boundaryGap": false,
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }],
"yAxis": [{ "type": "value", "name": "kWh" }],
"series": [
{ "name": "Household", "type": "line", "stack": "Total", "color": "#5b8dd9",
"areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
{ "name": "Wallbox", "type": "line", "stack": "Total", "color": "#00a3a3",
"areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
{ "name": "Heat pump", "type": "line", "stack": "Total", "color": "#3a5fa0",
"areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
{ "type": "pie", "center": ["50%", "28%"], "radius": "30%",
"label": { "formatter": "{b}: {c} kWh ({d}%)" },
"data": [
{ "name": "Household", "value": 0, "itemStyle": { "color": "#5b8dd9" } },
{ "name": "Wallbox", "value": 0, "itemStyle": { "color": "#00a3a3" } },
{ "name": "Heat pump", "value": 0, "itemStyle": { "color": "#3a5fa0" } }
]
}
]
}Note: The line series now have
"data": []— the script fills them in, so the initial placeholder is empty. The pie slices start with"value": 0for the same reason. All visual settings (colors, layout, labels) are defined here in the state, not in the script.
Replace the script from A1 Part B with the version below. The script still only updates data — but it now handles two chart types: line series (daily arrays) and pie slices (weekly totals).
const stateHousehold = '0_userdata.0.energy.consumption.household';
const stateWallbox = '0_userdata.0.energy.consumption.wallbox';
const stateHeatpump = '0_userdata.0.energy.consumption.heatpump';
const chartState = '0_userdata.0.flexcharts.energy.chart';
createState(chartState, '', { name: 'Energy chart', type: 'string', role: 'json', read: true, write: true }, () => {
buildAndSaveChart();
});
for (const id of [stateHousehold, stateWallbox, stateHeatpump]) {
on({ id: id, ack: false }, () => { buildAndSaveChart(); });
}
function buildAndSaveChart() {
const household = JSON.parse(getState(stateHousehold).val || '[]');
const wallbox = JSON.parse(getState(stateWallbox).val || '[]');
const heatpump = JSON.parse(getState(stateHeatpump).val || '[]');
const sum = arr => arr.reduce((a, b) => a + b, 0);
const dataMap = { 'Household': household, 'Wallbox': wallbox, 'Heat pump': heatpump };
// Read the chart definition from the state — the script only updates the data values.
const option = JSON.parse(getState(chartState).val || '{}');
for (const s of option.series || []) {
if (s.type === 'line' && s.name in dataMap) {
// Fill in the daily values for each area chart series.
s.data = dataMap[s.name];
} else if (s.type === 'pie') {
// Fill in the weekly total for each pie slice.
for (const item of s.data || []) {
if (item.name in dataMap) item.value = sum(dataMap[item.name]);
}
}
}
setState(chartState, JSON.stringify(option), true);
}The URL is unchanged from A1:
http://localhost:8082/flexcharts/echarts.html?source=state&id=0_userdata.0.flexcharts.energy.chart&sse
The combined chart should appear immediately. Try changing a value in one of the energy states (ack unchecked) — both the area chart and the pie update together.
The script loops over all series in the chart definition and acts differently depending on the series type:
for (const s of option.series || []) {
if (s.type === 'line' && s.name in dataMap) {
s.data = dataMap[s.name]; // daily array → line series
} else if (s.type === 'pie') {
for (const item of s.data || []) {
if (item.name in dataMap)
item.value = sum(dataMap[item.name]); // weekly total → pie slice
}
}
}All other properties — colors, label formatter, center position, radius, grid layout — stay exactly as you defined them in the chart state. The script never touches them.
Note: The legend controls both the area series and the corresponding pie slice — clicking "Wallbox" in the legend hides the Wallbox area and its pie slice at the same time, because both share the same name.
-
Cookbook A3 — Make the pie react to hover events on the area chart using
javascript-stringify
Cookbook A — From Scratch
Cookbook B — AI-Assisted