preface

Based on my recent participation in the research of the company’s Echarts report function, I encountered a lot of pits. Here, I will share the solution of several series loading instances involved in echarts asynchronous loading JSON data.

Problem description

When we load echarts complex graphics, such as line charts combined with bar charts, we will involve multiple series styles. For example,

option = {
    tooltip: {
        trigger: 'axis',
        formatter: function(params, ticket, callback) {

            var res = params[0].name;

            for (var i = 0, l = params.length; i < l; i++) {
                if (params[i].seriesType === 'line') {
                    res += '<br/>' + params[i].seriesName + ':' + (params[i].value ? params[i].value : The '-') + 'h';
                } else {
                    res += '<br/>' + params[i].seriesName + ':' + (params[i].value ? params[i].value : The '-') + '个'; }}return res;

        }
    },
    grid: {
        containLabel: true
    },
    legend: {
        data: ['time'.'Per capita'.'Population number']
    },
    xAxis: [{
        type: 'category',
        axisTick: {
            alignWithLabel: true
        },
        data: ['一月'.'二月'.'march'.'in April'.'may'.'June'.'July'.'August'.'September'.'October'.November.December]
    }],
    dataZoom: [{
        type: 'slider',
        xAxisIndex: 0,
        filterMode: 'empty',
        start: 0,
        end: 100
    }, {
        type: 'slider',
        yAxisIndex: 0,
        filterMode: 'empty',
        start: 0,
        end: 100
    }, {
        type: 'inside',
        xAxisIndex: 0,
        filterMode: 'empty',
        start: 0,
        end: 100
    }, {
        type: 'inside',
        yAxisIndex: 0,
        filterMode: 'empty',
        start: 0,
        end: 100
    }],
    yAxis: [{
        type: 'value',
        name: 'time',
        min: 0,
        position: 'left',
        axisLabel: {
            formatter: '{value} h'}}, {type: 'value',
        name: 'number',
        min: 0,
        position: 'right',
        axisLabel: {
            formatter: '{value}'
        }
    }],
    series: [{
        name: 'time'.type: 'line',
        label: {
            normal: {
                show: true,
                position: 'top',
            }
        },
        lineStyle: {
            normal: {
                width: 3,
                shadowColor: 'rgba (0,0,0,0.4)',
                shadowBlur: 10,
                shadowOffsetY: 10
            }
        },
        data: [1, 13, 37, 35, 15, 13, 25, 21, 6, 45, 32, 2]
    }, {
        name: 'Per capita'.type: 'bar',
        yAxisIndex: 1,
        label: {
            normal: {
                show: true,
                position: 'top'
            }
        },
        data: [22, 22, 23, 77, 24, 55, 55, 89, 98, 164, 106, 224]
    }, {
        name: 'Population number'.type: 'bar',
        yAxisIndex: 1,
        label: {
            normal: {
                show: true,
                position: 'top'
            }
        },
        data: [201, 222, 223, 777, 244, 255, 555, 879, 938, 1364, 1806, 2324]
    }]
};
   
Copy the code

We find that the Echarts chart is a double Y-axis and consists of bars and broken lines. Time is shown in a line graph, and the number per capita and the total number are shown in a bar graph. And this is a dead write sample, so the data in our actual application must be asynchronously loaded data, json string data format is the same, how to asynchronously load this different series with JSON string?

Actual solution

Here, the main building with their own projects as an example, posted the core code. First, the obtained JSON string format is shown in the figure below. The data format header for Total is data. Namely: data: {total: {date:… }}

var option = {
    title: {
            text: 'Transaction Volume Trend Chart'
        },
    tooltip: {
            trigger: 'axis', axisPointer: {// Axis indicator, axis trigger workstype: 'shadow'// The default is a straight line, which can be:'line' | 'shadow'
            },
   formatter: function (params, ticket,callback){
                var res = params[0].name;

                for (var i = 0, l = params.length; i < l; i++) {
                    if (params[i].seriesType === 'line') {
                        res += '<br/>' + params[i].seriesName + ':' + (params[i].value ? params[i].value : The '-') + '元';
                    } else {
                        res += '<br/>' + params[i].seriesName + ':' + (params[i].value ? params[i].value : The '-') + '元'; }}return res;
            }
        },
        legend: {
            data: [],
            align: 'right',
            right: 10
        },
        grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
        },
        xAxis: [{
            type: 'category',
            data: []
        }],
        yAxis: [{
            type: 'value',
            name: 'Total price (yuan)',
            axisLabel: {
                formatter: '{value}'
            }
        }],
        series: []
    };
Copy the code

Second, the three places where the data needs to be loaded are Legend (for legend components),xAxis(for X-axis data), and Series (for chart types and styles, etc.), all set to default. Then, our core code comes in, and we end up with a series that has two different chart types. So, here we define two different chart types respectively, namely broken line and column, namely:

Var ItemLine = var ItemLine =function () {
        return {
            name: ' '.type: 'line',
            label: {
                normal: {
                    show: true,
                    position: 'top',
                }
            },
            lineStyle: {
                normal: {
                    width: 3,
                    shadowColor: 'rgba (0,0,0,0.4)', shadowBlur: 10, shadowOffsetY: 10 } }, data: [] } }; Var ItemBar =function () {
        return {
            name: ' '.type: 'bar',
            data: []
        }

    }
Copy the code

Define 3 variables to store values of Legend,xAxis, and Series respectively.

var legends=[];
var xDateArr=[];
var SeriesTotal=[];
Copy the code

Assign the JSON string to three variables. This is very important! Very important! Very important! Say important things three times. Going back to our JSON string, notice that the header is data. Let’s iterate over the JSON string:

// Assign xDataArr=data.total.date;for (var k inData.total.element) {// Assign the value to legend lengends.push(data.total.element[k].name); // Core, assign value to series, separate packaging idea.if (k == 0) {
            var itemLine = new ItemLine();
            itemLine.name = data.total.element[k].name;
            itemLine.data = data.total.element[k].value;
            SeriesTotal.push(itemLine);
        } else{ var itemBar = new ItemBar(); itemBar.name = data.total.element[k].name; itemBar.data = data.total.element[k].value; SeriesTotal.push(itemBar); }}Copy the code

Of course, HERE I use subscript to do segmentation, friends can also use JSON as a symbol to split two different series, the main idea is to divide the packaging, so that we can realize the asynchronous loading of multiple series of data. Finally, assign these three variables to option and load option into the DOM container.

var myChartTransactionTotal = echarts.init(document.getElementById('main_chart_transaction_total')); option.legend.data = lengends; XAxis [0] : xAxis[0] : xAxis[0] : xAxis[0] : xAxis[0] : xAxis[0] : xAxis[0] option.xAxis[0].data = data.total.date; option.series = SeriesTotal; // We'd better add it heretrueArgument, otherwise the previous data will not be cleared when the chart is switched. myChartTransactionTotal.setOption(option,true);
Copy the code

Let’s see if it’s easy to do in practice. If you have any questions, welcome to exchange and discuss!