1

I'm configuring the legend of my scatter chart using ngx-echarts. Instead of a fixed symbol to represent my data series in the legend, I would like to display an icon that represents a checked checkbox when active and an unchecked checkbox when inactive.

I achieved the first one using the "icon" parameter:

this.chartOption = {
  legend: {
   data: {
      name: 'serie1',
      icon: 'path://m419-321 289-290-43-43-246 247-119-119-43 43 162 162ZM180-120q-24 0-42-18t-18-42v-600q0-24 18-42t42-18h600q24 0 42 18t18 42v600q0 24-18 42t-42 18H180Z'
      },
   data: {
      name: 'serie2',
      icon: 'path://m419-321 289-290-43-43-246 247-119-119-43 43 162 162ZM180-120q-24 0-42-18t-18-42v-600q0-24 18-42t42-18h600q24 0 42 18t18 42v600q0 24-18 42t-42 18H180Z'
      }
   }
}

But, while the documentation mentions inactiveColor, inactiveBorderColor etc. to configure the behaviour of the legend when inactive, I don't see an equivalent for the icon (like "inactiveIcon").

Is there anything I've missed?

Thanks in advance

GillesG
  • 13
  • 3

1 Answers1

0

You can use the legendselectchanged event to dynamically change the icon (or any other) properties of the legend.

Assuming that you set the svg path in a string and create the echarts instance myChart by the standard recipe:

const myChart = echarts.init(dom, null, {
    renderer: 'canvas',
    useDirtyRect: false
});

const iconCheckedPath = 'path://m419-321 289-290-43-43-246 247-119-119-43 43 162 162ZM180-120q-24 0-42-18t-18-42v-600q0-24 18-42t42-18h600q24 0 42 18t18 42v600q0 24-18 42t-42 18H180Z';

with the initial legend option as

const option = {
    // ........ other options
    legend: {
        data: [{
                name: 'serie1',
                icon: iconCheckedPath
            },
            {
                name: 'serie2',
                icon: iconCheckedPath
            }
        ],
        // .....        
    }
    // ....
};
myChart.setOption(option);

you may set the event handler as

myChart.on('legendselectchanged', function ({selected}) {
    myChart.setOption({
        legend:{
            data: Object.entries(selected)
                .map(([name, nameSelected]) =>
                    ({name, icon: nameSelected ? iconCheckedPath: 'square'}))
        }
    })
});

Here's a working example in a codesandbox, forked from one of echart's standard examples.

In case there are other options in legend.data, one may merge them with the new options with something on the lines of

myChart.on('legendselectchanged', function ({selected}) {
    const actualData = myChart.getOption().legend[0].data;
    Object.entries(selected).forEach(([name, nameSelected])=>{
      const dataObj = actualData.find(({name: actualName})=>actualName === name);
      if(dataObj){
        dataObj.icon = nameSelected ? iconCheckedPath: 'square';
      }
    });
    myChart.setOption({
        legend:{
            data: actualData
        }
    })
});

Here's a codepen example with that.

kikon
  • 3,670
  • 3
  • 5
  • 20
  • This works brilliantly! The only issue left is that map function overrides the other parameters that were defined in the legend property - itemStyle and textStyle. Do you know of any way to maintain them as they are? – GillesG Jun 13 '23 at 15:00
  • The function `setOption` typically merges (by default) the existing options with the new ones, but it seems it doesn't work for arrays. I added a version that merges the options in `legend.data` manually. – kikon Jun 13 '23 at 15:41
  • 1
    This is awesome. It wasn't working initially - I was receiving an error saying `the legend property comes from an index signature, so it must be accessed with ['legend']`. But I found a fix in another stackoverflow thread (changing a parameter in tsconfig.json) that did the trick. It works brilliantly now. Thanks for the quick and super helpful answers, kikon. – GillesG Jun 13 '23 at 20:43