skip to Main Content

Considering the Apache Echart library and this example : https://echarts.apache.org/examples/en/editor.html?c=heatmap-cartesian

If I add the following code snippet :

myChart.on('click', function (params) {
    myChart.dispatchAction({
        type: 'highlight',
        seriesIndex: [0],
    });
});

It allows the user to click on a data of the heatmap and it will hightlight all data.

The hightlight action (https://echarts.apache.org/en/api.html#action) can be used with seriesIndex, seriesId and seriesName. However, heatmap are built with only one serie of data.

How could I proceed to hightlight only one line (or one value of X, or one day of the week-end) when I click on a value belonging to this line ?
For exemple, how can I highlight all data for ‘Monday’ if I click a data associated with ‘Monday’.

I have been trying to play around and :

  • working with multiple series instead of one breaks the heatmap behavior.
  • I can get more details about where I click with the params variable of the event listener. I could find an algorythm that focus only data of the line I focus on, but anyway the dispatchAction ‘highlight’ works only for the whole serie.

TLDR : With Apache Echart and the heatmap type of plot, how can I use highlight action toward a single value of X (or heatmap line) ?

2

Answers


  1. Chosen as BEST ANSWER

    Here is a code snippet that highlights a line of the heatmap and that also downplay (opposite of highlight) an hypothetical previously clicked line :

    myChart.on('click', function (params) {
    if (event.target) {
        myChart.dispatchAction({
            type: 'downplay',
            seriesIndex: [0],
        });
        const seriesIndex = params.seriesIndex,
            data = myChart.getOption().series[seriesIndex].data;
        const [x, y] = params.data;
        const dataIndex = data.map(([xData, yData, value], idx) => y === yData && Number.isFinite(value) ? idx : null).filter(v => v !== null);
        myChart.dispatchAction({
            type: 'highlight',
            seriesIndex,
            dataIndex
        });
    }
    

    Then another code snippet that's downplay any highlighted line if you click somewhere out of heatmap (but on plot zone of course) :

    myChart.getZr().on('click', function (event) {
    if (!event.target) {
        myChart.dispatchAction({
            type: 'downplay',
            seriesIndex: [0],
        });
    }
    });
    

  2. You can select specific items from the series by setting the dataIndex in the call action object,
    see the the api docs for action.highlight.

    The dataIndex of the clicked item may be retrieved from params.dataIndex, where params
    is the argument in the click handler you defined; also useful are the corresponding x and y
    components, from params.data ([x, y] = params.data).

    The dataIndex is simply the index of the item’s data in the series data array;
    params.seriesIndex may be used to identify the series, especially if there is more than one.

    An example handler that selects a line, that is all the items with the same y value as the clicked item, (the same day of the week):

    myChart.on('click', function (params) {
        const data = myChart.getOption().series[params.seriesIndex].data;
        const [x, y] = params.data;
        // get all indices of data with the same y (day of the week)
        const dataIndex = data.map(([xData, yData, value], idx) => y === yData && Number.isFinite(value) ? idx : null).
        filter(v => v !== null);
        myChart.dispatchAction({
            type: 'highlight',
            seriesIndex: [0],
            dataIndex
        });
    });
    

    Snippet:

    const myChart = echarts.init(document.getElementById('main'));
    
    // prettier-ignore
    const hours = [
        '12a', '1a', '2a', '3a', '4a', '5a', '6a',
        '7a', '8a', '9a', '10a', '11a',
        '12p', '1p', '2p', '3p', '4p', '5p',
        '6p', '7p', '8p', '9p', '10p', '11p'
    ];
    // prettier-ignore
    const days = [
        'Saturday', 'Friday', 'Thursday',
        'Wednesday', 'Tuesday', 'Monday', 'Sunday'
    ];
    // prettier-ignore
    const data = [[0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2], [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0], [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2], [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7], [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2], [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0], [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2], [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5], [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4], [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4], [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5], [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1], [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1], [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4], [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1], [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0], [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0], [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1], [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6], [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0], [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0], [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0], [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0], [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]]
        .map(function (item) {
            return [item[1], item[0], item[2] || '-'];
        });
    
    const option = {
        tooltip: {
            position: 'top'
        },
        grid: {
            height: '50%',
            top: '10%'
        },
        xAxis: {
            type: 'category',
            data: hours,
            splitArea: {
                show: true
            }
        },
        yAxis: {
            type: 'category',
            data: days,
            splitArea: {
                show: true
            }
        },
        visualMap: {
            min: 0,
            max: 10,
            calculable: true,
            orient: 'horizontal',
            left: 'center',
            bottom: '15%'
        },
        series: [
            {
                name: 'Punch Card',
                type: 'heatmap',
                data: data,
                label: {
                    show: true
                },
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
        ]
    };
    
    option && myChart.setOption(option);
    
    myChart.on('click', function (params) {
        const seriesIndex = params.seriesIndex,
            data = myChart.getOption().series[seriesIndex].data;
        const [x, y] = params.data;
        // get all indices of data with the same y (day of the week)
        const dataIndex = data.map(([xData, yData, value], idx) => y === yData && Number.isFinite(value) ? idx : null).filter(v => v !== null);
        myChart.dispatchAction({
            type: 'highlight',
            seriesIndex,
            dataIndex
        });
    });
    #main {
      position: relative;
      height: 100vh;
      overflow: hidden;
    }
    <div id="main"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js" integrity="sha512-VdqgeoWrVJcsDXFlQEKqE5MyhaIgB9yXUVaiUa8DR2J4Lr1uWcFm+ZH/YnzV5WqgKf4GPyHQ64vVLgzqGIchyw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search