echarts

How to know the actual target of click event in echarts?


I'd like to add an annotations feature to my echarts diagram. It'll be marked as a green dotted line with a green square marker if there's any annotation. When the user clicks the green square marker, a popup will open to show the actual annotation.

When I run the command below, it's triggered whenever I click anywhere on the annotation marker line. How can I tell if the user clicks specifically on the green square marker?

myChart.on('click', "series.line", function(params) {
  console.log('normal click series.markLine', params)
})

Here is the demo: https://codepen.io/lora999/pen/azbGPKY

enter image description here


Solution

  • If you explore params in your myChart.on('click', "series.line", function(params){... you can find ways to identify that the rectangle was clicked. The most straightforward one seems to be params.event.target.type === 'rect' (tested with renderer svg also):

    myChart.on('click', "series.line", function(params) {
        if(params.event.target.type === 'rect'){
            console.log('Rectangle clicked');
            // use params.data.name or params.data._id to further
            // identify the target, if multiple annotations are added
        }
    });
    

    Runnable snippet:

    const myChart = echarts.init(document.getElementById("chart-container"), null, {
       renderer: "canvas",
       useDirtyRect: false,
    });
    
    const option = {
        "useUTC": false,
        "grid": {
            "containLabel": true,
            "left": 35,
            "right": 40,
            "top": 40,
            "bottom": 40
        },
        "xAxis": {
            "type": "time",
        },
        "yAxis": {
            "type": "value",
        },
        "tooltip": {
            appendTo: 'body',
            "borderColor": "transparent",
            "show": true,
            "trigger": "axis",
            enterable: true,
        },
        "legend": {
            "orient": "horizontal",
            "show": true,
            "type": "scroll",
            "bottom": 0,
        },
        "series": [
            {
                "name": "series1",
                "data": [
                    [
                        1041811200000,
                        30429.64
                    ],
    
                    [
                        1043625600000,
                        99323.95999999999
                    ],
    
                    [
                        1050883200000,
                        4219.2
                    ],
                ],
                "connectNulls": true,
                "type": "line",
                "smooth": false,
    
                "showSymbol": false,
    
            },
            {
                id: 'Annotation',
                name: 'annotation',
                type: "line",
                markLine: {
                    symbol: 'none',
                    label: {
                        show: true,
                        formatter: '{icon|}',
                        rich: {
                            icon: {
                                height: 20,
                                width: 20,
                                backgroundColor: 'green',
                                _id:'__test__'
                            },
                            _id:'__test__'
                        }
                    },
                    data: [
                        {
                            name: 'annotationLine',
                            xAxis: 1043625600000,
                            lineStyle: {
                                width: 2,
                                color:'green'
                            },
                            _id: 'annotationLine'
                        },
                    ]
                }
    
            },
        ],
    };
    
    
    myChart.on('click', "series.line", function(params) {
        if(params.event.target.type === 'rect'){
            console.log('Rectangle clicked');
            // use params.data.name or params.data._id to further
            // identify the target, if multiple annotations are added
        }
    });
    
    
    myChart.setOption(option);
    
    window.addEventListener('resize', myChart.resize);
    <div id="chart-container" style="height:400px; min-width: 800px"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.6.0/echarts.min.js"></script>

    However, the safest solution is to separate the rectangle from the line, make them two different annotations, the rectangle implemented as a markPoint:

    const myChart = echarts.init(document.getElementById("chart-container"), null, {
       renderer: "canvas",
       useDirtyRect: false,
    });
    
    const option = {
        "useUTC": false,
        "grid": {
            "containLabel": true,
            "left": 35,
            "right": 40,
            "top": 40,
            "bottom": 40
        },
        "xAxis": {
            "type": "time",
        },
        "yAxis": {
            "type": "value",
        },
        "tooltip": {
            appendTo: 'body',
            "borderColor": "transparent",
            "show": true,
            "trigger": "axis",
            enterable: true,
        },
        "legend": {
            "orient": "horizontal",
            "show": true,
            "type": "scroll",
            "bottom": 0,
        },
        "series": [
            {
                "name": "series1",
                "data": [
                    [
                        1041811200000,
                        30429.64
                    ],
    
                    [
                        1043625600000,
                        99323.95999999999
                    ],
    
                    [
                        1050883200000,
                        4219.2
                    ],
                ],
                "connectNulls": true,
                "type": "line",
                "smooth": false,
    
                "showSymbol": false,
    
            },
            {
                id: 'Annotation',
                name: 'annotation',
                type: "line",
                markLine: {
                    symbol: 'none',
                    silent: true, // doesn't respond to click
                    label: {
                        show: false
                    },
                    data: [
                        {
                            name: 'annotationLine',
                            xAxis: 1043625600000,
                            lineStyle: {
                                width: 2,
                                color:'green'
                            },
                            _id: 'annotationLine'
                        },
                    ]
                },
                markPoint: {
                    symbol: 'rect',
                    symbolSize: 20,
                    symbolOffset: [0, -10],
                    itemStyle: {
                        color: 'green'
                    },
                    label: {
                        show: false,
                    },
                    data: [
                        {
                            name: 'annotationPoint',
                            coord: [1043625600000, 100000],
                            _id: 'annotationPoint'
                        },
                    ]
                }
    
            },
        ],
    };
    
    
    myChart.on('click', "series.line", function(params) {
        // in this scenario, only the markPoint is responding to clicks; but if other items are
        // added, params.componentType and/or params.data.name (or _id) may be used to identify the target
        if(params.componentType === 'markPoint'){
            console.log('Rectangle clicked', params.data.name);
        }
    })
    
    
    myChart.setOption(option);
    
    window.addEventListener('resize', myChart.resize);
    <div id="chart-container" style="height:400px; min-width: 800px"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.6.0/echarts.min.js"></script>

    or using the icon label, as in the original code (svg renderer used):

    const myChart = echarts.init(document.getElementById("chart-container"), null, {
       renderer: "svg",
       useDirtyRect: false,
    });
    
    const option = {
        "useUTC": false,
        "grid": {
            "containLabel": true,
            "left": 35,
            "right": 40,
            "top": 40,
            "bottom": 40
        },
        "xAxis": {
            "type": "time",
        },
        "yAxis": {
            "type": "value",
        },
        "tooltip": {
            appendTo: 'body',
            "borderColor": "transparent",
            "show": true,
            "trigger": "axis",
            enterable: true,
        },
        "legend": {
            "orient": "horizontal",
            "show": true,
            "type": "scroll",
            "bottom": 0,
        },
        "series": [
            {
                "name": "series1",
                "data": [
                    [
                        1041811200000,
                        30429.64
                    ],
    
                    [
                        1043625600000,
                        99323.95999999999
                    ],
    
                    [
                        1050883200000,
                        4219.2
                    ],
                ],
                "connectNulls": true,
                "type": "line",
                "smooth": false,
    
                "showSymbol": false,
    
            },
            {
                id: 'Annotation',
                name: 'annotation',
                type: "line",
                markLine: {
                    symbol: 'none',
                    silent: true, // doesn't respond to click
                    label: {
                        show: false
                    },
                    data: [
                        {
                            name: 'annotationLine',
                            xAxis: 1043625600000,
                            lineStyle: {
                                width: 2,
                                color:'green'
                            },
                            _id: 'annotationLine'
                        },
                    ]
                },
                markPoint: {
                    symbol: 'rect',
                    symbolSize: 20,
                    symbolOffset: [0, -10],
                    itemStyle: {
                        color: 'green'
                    },
                    label: {
                        show: false,
                    },
                    data: [
                        {
                            name: 'annotationPoint',
                            coord: [1043625600000, 100000],
                            _id: 'annotationPoint'
                        },
                    ]
                }
    
            },
        ],
    };
    
    
    myChart.on('click', "series.line", function(params) {
        // in this scenario, only the markPoint is responding to clicks; but if other items are
        // added, params.componentType and/or params.data.name (or _id) may be used to identify the target
        if(params.componentType === 'markPoint'){
            console.log('Rectangle clicked', params.data.name);
        }
    });
    
    
    myChart.setOption(option);
    
    window.addEventListener('resize', myChart.resize);
    <div id="chart-container" style="height:400px; min-width: 800px"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.6.0/echarts.min.js"></script>