Skip to content

Cookbook A2 Adding a Pie Chart

MyHomeMyData edited this page May 7, 2026 · 4 revisions

Cookbook A2 — Adding a Pie Chart

What you will build

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.

flexcharts_wiki_a2_1

Just as in A1, the chart state remains the master for the chart definition. You will:

  1. Update the chart state with a new JSON that adds the pie chart structure and adjusts the layout
  2. 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.

Prerequisites

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

Step 1 — Update the chart state

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": 0 for the same reason. All visual settings (colors, layout, labels) are defined here in the state, not in the script.

Step 2 — Update 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);
}

Step 3 — Open in the browser

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.


How the script handles two chart types

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.


What's next

  • Cookbook A3 — Make the pie react to hover events on the area chart using javascript-stringify

Clone this wiki locally