Skip to content

Cookbook A3 Interactive Charts

MyHomeMyData edited this page May 7, 2026 · 3 revisions

Cookbook A3 — Interactive Charts: Hover-Driven Pie

What you will build

An interactive combined chart: an area chart in the lower half and a pie chart in the upper half. When the mouse moves over a day in the area chart, the pie automatically updates to show the energy distribution for exactly that day.

flexcharts_wiki_a3_1

The key new concept: the chart state now holds an array of two strings — the chart option and a browser-side event handler. flexcharts injects both into the page on load.

Prerequisites

Completed Cookbook A1 and Cookbook A2. The chart state and energy data states must be in place.


How the state format evolves

Up to now the chart state contained a single option string. In A3 it becomes a JSON array:

Index Content
[0] Chart option — the same kind of string as before
[1] Event handler — JavaScript code that runs in the browser after the chart is rendered

flexcharts detects the array automatically: arr[0] is injected as the chart option, arr[1] is evaluated in the browser. For SSE updates, only arr[0] is refreshed — the event handler is registered once on initial load and stays active.


Step 1 — Update the chart state

Open 0_userdata.0.flexcharts.energy.chart in the Objects editor and replace its value with the JSON array below. Save (ack unchecked).

[
  "{title:{text:'Weekly Energy Consumption',left:'center'},tooltip:{trigger:'axis',showContent:false},legend:{top:'8%'},toolbox:{feature:{saveAsImage:{}}},color:['#5b8dd9','#00a3a3','#3a5fa0'],dataset:{source:[['category','Mon','Tue','Wed','Thu','Fri','Sat','Sun'],['Household',12,11,13,12,14,9,10],['Wallbox',0,22,0,0,22,0,0],['Heat pump',8,9,10,9,8,6,7]]},xAxis:{type:'category'},yAxis:{gridIndex:0},grid:{top:'55%'},series:[{type:'line',smooth:true,seriesLayoutBy:'row',areaStyle:{},emphasis:{focus:'series'}},{type:'line',smooth:true,seriesLayoutBy:'row',areaStyle:{},emphasis:{focus:'series'}},{type:'line',smooth:true,seriesLayoutBy:'row',areaStyle:{},emphasis:{focus:'series'}},{type:'pie',id:'pie',radius:'22%',center:['50%','33%'],emphasis:{focus:'self'},label:{formatter:'{b}: {@Mon} kWh ({d}%)'},encode:{itemName:'category',value:'Mon',tooltip:'Mon'}}]}",
  "myChart.on('updateAxisPointer',function(e){let t=e.axesInfo[0];if(t){let i=t.value+1;myChart.setOption({series:{id:'pie',label:{formatter:'{b}: {@['+i+']} kWh ({d}%)'},encode:{value:i,tooltip:i}}})}});"
]

What changed compared to A2:

  • The data is now in a shared dataset (dataset.source) — a table with one row per energy category and one column per day. The area chart series and the pie chart both read from this single table.
  • tooltip: {trigger: 'axis', showContent: false} — the axis pointer fires when the mouse moves, but no floating tooltip is shown. The pie acts as the visual feedback instead.
  • [1] — the event handler string: listens for updateAxisPointer events and updates the pie's encode to show the column matching the hovered day.

Step 2 — Open in the browser

The URL is unchanged:

http://localhost:8082/flexcharts/echarts.html?source=state&id=0_userdata.0.flexcharts.energy.chart&sse

Move the mouse over the area chart. The pie updates instantly to show the distribution for each day.

flexcharts_wiki_a3_2

How it works

The shared dataset

Instead of individual data arrays per series (as in A1/A2), A3 uses a single dataset.source table:

           Mon   Tue   Wed   Thu   Fri   Sat   Sun
Household   12    11    13    12    14     9    10
Wallbox      0    22     0     0    22     0     0
Heat pump    8     9    10     9     8     6     7

Each line series uses seriesLayoutBy: 'row' to read one row from this table. The pie series uses encode: {itemName: 'category', value: 'Mon'} to read a column — initially Monday.

The event handler

The event handler string in arr[1] is evaluated in the browser once after the chart is initialized:

myChart.on('updateAxisPointer', function(e) {
    let t = e.axesInfo[0];
    if (t) {
        let i = t.value + 1;  // axis index 0–6 → dataset column 1–7
        myChart.setOption({
            series: {
                id: 'pie',
                label:  { formatter: '{b}: {@[' + i + ']} kWh ({d}%)' },
                encode: { value: i, tooltip: i }
            }
        });
    }
});

When the mouse moves over the area chart, updateAxisPointer fires with the hovered axis position. t.value is the day index (0 = Mon, …, 6 = Sun). Adding 1 gives the dataset column index. The pie's encode.value is updated to that column — ECharts re-reads the dataset and redraws the pie for that day.

JavaScript syntax vs. strict JSON

You may have noticed that the option string uses unquoted keys and single quotes — not strict JSON:

{title:{text:'Weekly Energy Consumption',...}, ...}

This is valid JavaScript object notation. flexcharts evaluates it in the browser using new Function('return ' + optionString)(), which handles any valid JavaScript expression. This is the same format produced by the npm package javascript-stringify, which is used in source=script scripts (see Template 3 and Template 4) when the chart option contains JavaScript functions that JSON.stringify() cannot serialize — for example a custom tooltip formatter like value => value.toFixed(2).

For the charts in this cookbook, all formatters use ECharts template strings ('{b}: {c}') rather than JavaScript functions, so JSON.stringify() is sufficient.


Going further

Live data with a script

To keep the interactive chart updated from real data states (like in A1/A2), a script would:

  1. Read the three energy states
  2. Parse the chart state as a JSON array: const arr = JSON.parse(getState(chartState).val)
  3. Parse the option string: const option = new Function('return ' + arr[0])()
  4. Update option.dataset.source with the fresh data
  5. Serialize back: arr[0] = JSON.stringify(option) (note: use javascript-stringify if the option contains functions)
  6. Write: setState(chartState, JSON.stringify(arr), true)

SSE then delivers only the updated option (arr[0]) to the browser — the event handler in arr[1] is not re-evaluated and remains active.

When to use source=script instead

For fully code-driven charts, the source=script pattern (using onMessage) gives you more flexibility: the script generates the option at request time, can access URL parameters, and can use javascript-stringify for options containing real JavaScript functions. The script returns [strify.stringify(option), eventHandlerString] — the same array format as the state, just produced dynamically. See Template 4 for a complete example.


Apache ECharts resources

The examples in this cookbook are a small sample of what ECharts can do. Apache provides a rich set of tools to help you explore and build further:

Resource What it's for
Examples gallery Hundreds of interactive chart examples with live editors — the best starting point for new chart ideas
Option reference Complete documentation of every chart option, series type, and property
Handbook Tutorials covering concepts like datasets, events, theming, and responsive charts
Theme Builder Visual editor for custom themes — export as JSON and pass to flexcharts (see Template 5)

The workflow that works well: find a chart in the Examples gallery that matches what you want, open its editor, adapt the data and options, then transfer the result to a flexcharts state or script.


Cookbook summary

These three articles covered the core flexcharts patterns:

Article Pattern Key concept
A1 State as master, simple option string SSE, createState, data injection
A2 State as master, extended option string Combined chart types, computed totals
A3 State as master, array [option, eventHandler] Browser events, shared dataset, JavaScript syntax

For more examples and advanced patterns, see the flexcharts templates and the flexcharts README.