两个不同来源数据合并的图表

要求:一个图表中显示两个不同来源的数据,来源数据结构不一致,日期或数据均有缺失,每个日期对应数据要为之前数据总和且成一个上升的趋势。
思路:

  1. 两份数据转成统一结构(如果两份数值类型不一样还需要单独转成统一类型,我的项目excel返回的数值,需要自己算百分比)
  2. 合并数据
  3. 补齐日期和数据:比较数据日期取出最大值最小值,并计算出相差天数,补全缺失日期,再补全数据;
  4. 转为echarts可用格式
    以下是用到的一些技术示例,非源代码(源代码太复杂懒得整理)
    在这里插入图片描述
补齐数据日期
function fnFillTheDataDate(){
	// 已合并后数据
    var oData= {
	"桩基":{"data":[5,10,15],"date":["2020-01-01","2020-01-10","2020-01-5"]},
	"隧道":{"data":[1,5,10],"date":["2020-01-02","2020-01-5","2020-01-15"]},
	"土方量":{"data":[10,15,20],"date":["2020-01-06","2020-01-2","2020-01-10"]}
	}
	var mixDate = []; // 每类最大日期and最小日期集合
	var mixMaxTimestamp= 0, mixMinTimestamp = 0; // 最终的最大日期、最小日期
	// 获取完整日期 2020-01-01 ~ 2020-01-15
	for(var key in oData){
		var dates = oData[key].date
		oData[key]['timestamp'] = [];
		for(var i=0; i<dates.length; i++){
			oData[key]['timestamp'].push(new Date(dates[i]))
		}
		var minDate = Math.min.apply(null,oData[key]['timestamp'])
		var maxDate = Math.max.apply(null,oData[key]['timestamp'])
		mixDate.push(maxDate, minDate)
	}
	if(mixDate[0]){
		var mixMinTimestamp = Math.min.apply(null,mixDate)
		var mixMaxTimestamp= Math.max.apply(null,mixDate)
    }
    var d_value = (mixMaxTimestamp - mixMinTimestamp) / 1000 / 3600 / 24; // 日期差
    var timeline = []; // 完整的日期
    if(d_value){
	    for(var i=0; i<=d_value; i++){  //35
	      timeline.push(fnGetIntervalDate(i, mixMinTimestamp).date)
	    }
    }
    // 补充日期
    if(timeline[0]){ 
	    for(var key in oData){
	      var oItem= oData[key];
	      var data = oItem.data;
	      var date = oItem.date;
	      for(var i=0; i<timeline.length; i++){
	        var hasDate = 0
	        for(var j=0; j<date.length; j++){
	          if(timeline[i] == date[j]){
	            hasDate ++;
	            break
	          } 
	        }   
	        if(hasDate == 0) {
	          date.push(timeline[i])
	          data.push('') 
	        }
	      }
	    }
    }
    console.log(oData)
}
    
/** 获取间隔日期
 * @Descripttion: 
 * @param {*} days 增减天数
 * @param {*} startdate 开始日期
 * @return {*}
 * @Author: TinaZ
 * @Date: 2021-02-01
 */
function fnGetIntervalDate(days, startdate) {
    var days = days || 0;
    var currDate = startdate ? new Date(startdate).getTime() : new Date().getTime();
    var date =  new Date(currDate + days*24*60*60*1000);
    var Y = date.getFullYear();
    var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1);
    var D = date.getDate()<10 ? '0'+date.getDate() : date.getDate();
    var H = date.getHours()<10 ? '0'+date.getHours() : date.getHours();
    var m = date.getMinutes()<10 ? '0'+date.getMinutes() : date.getMinutes();
    var s = date.getSeconds()<10 ? '0'+date.getSeconds() : date.getSeconds();
    var sDate = Y + '-' + M + '-' + D;
    var sDatetime = Y + '-' + M + '-' + D + ' ' + H + ':' + m + ':' + s;
    return {date: sDate, datetime: sDatetime};
}

源数据与完成日期对比

按日期排序

实际项目中数据来源不同、结构不同,都需要转换成以下格式方可进行排序;

/** 排序并补齐缺失数据
 * @Descripttion: 
 * @param {*}
 * @return {*}
 * @Author: TinaZ
 * @Date: 2021-02-03
 */
function fnSortAndFillTheData(){
    var oSourcedata = {
        "桩基": {
            "data": [5, 10, 15, "", "", "", "", "", "", "", "", "", "", "", "", ""],
            "date": ["2020-01-01", "2020-01-10", "2020-01-16", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05", "2020-01-06", "2020-01-07", "2020-01-08", "2020-01-09", "2020-01-11", "2020-01-12", "2020-01-13", "2020-01-14", "2020-01-15"],
        },
        "隧道": {
            "data": [1, 5, 10, "", "", "", "", "", "", "", "", "", "", "", "", ""],
            "date": ["2020-01-02", "2020-01-16", "2020-01-15", "2020-01-01", "2020-01-03", "2020-01-04", "2020-01-05", "2020-01-06", "2020-01-07", "2020-01-08", "2020-01-09", "2020-01-10", "2020-01-11", "2020-01-12", "2020-01-13", "2020-01-14"],
        },
        "土方量": {
            "data": [10, 15, 20, "", "", "", "", "", "", "", "", "", "", "", "", ""],
            "date": ["2020-01-06", "2020-01-16", "2020-01-10", "2020-01-01", "2020-01-02", "2020-01-03", "2020-01-04", "2020-01-05", "2020-01-07", "2020-01-08", "2020-01-09", "2020-01-11", "2020-01-12", "2020-01-13", "2020-01-14", "2020-01-15"],
        }
    }
    var aNewData = []
    // 转换格式
    for(var key in oSourcedata){
        var aItem = []
        for(var i=0; i<oSourcedata[key].date.length; i++){
            var oItem = {}
            oItem['name'] = key
            oItem['data'] = oSourcedata[key].data[i]
            oItem['date'] = oSourcedata[key].date[i]
            aItem.push(oItem)
        }
        aNewData.push(aItem)
    }
    console.log("排序前格式",JSON.parse(JSON.stringify(aNewData))[1])
    
    // 排序
    for(var i=0; i<aNewData.length; i++){
        aNewData[i] = fnDateSort(aNewData[i])
    }
    console.log("排序后格式",JSON.parse(JSON.stringify(aNewData))[1])
    
    // 补齐缺失数据
    for(var i=0; i<aNewData.length; i++){
        for(var j=0; j<aNewData[i].length; j++){
            //对数据进行累加计算,并补齐
            aNewData[i][j].data = 
            aNewData[i][j-1] && aNewData[i][j-1].data ? 
            (aNewData[i][j].data ? aNewData[i][j-1].data + aNewData[i][j].data : aNewData[i][j-1].data) : aNewData[i][j].data;
            // aNewData[i][j].data = aNewData[i][j].data ? aNewData[i][j].data : aNewData[i][j-1]&&aNewData[i][j-1].data ? aNewData[i][j-1].data : aNewData[i][j].data;
        }        
    }
    console.log("补齐缺失数据",JSON.parse(JSON.stringify(aNewData[1])))

    // 按周显示
    var defaultday = new Date(aNewData[0][aNewData[0].length-1].date).getDay();
    var aWeekData = [];
    for(var k=0; k<aNewData.length; k++){
        aWeekData.push([])
        for(var n=0; n<aNewData[k].length; n++){
            var day = new Date(aNewData[k][n].date).getDay()
            if(day == defaultday){
                aWeekData[k].push(aNewData[k][n])
            }
        }
    }
    console.log("获取周数据", JSON.parse(JSON.stringify(aWeekData[1])))
}
fnSortAndFillTheData();
/** 日期排序
 * @Descripttion: 
 * @param {*} aData [{name:"",date:"",data:""},{name:"",date:"",data:""}]
 * @return {*}
 * @Author: TinaZ
 * @Date: 2021-02-03
 */
function fnDateSort(aData){
    return aData.sort(function(a,b){
        return Date.parse(a.date.replace(/-/g,"/")) - Date.parse(b.date.replace(/-/g,"/"))
    })
}

在这里插入图片描述

转为Echarts可用格式并创建图表
/** 创建图表
 * @Descripttion: 
 * @param {*} 
 * @return {*}
 * @Author: TinaZ
 * @Date: 2021-02-03
 */
function fnCreateEchart(){
   var aSourceData = [[{"name":"桩基","data":5,"date":"2020-01-02"},{"name":"桩基","data":5,"date":"2020-01-09"},{"name":"桩基","data":30,"date":"2020-01-16"}],[{"name":"隧道","data":1,"date":"2020-01-02"},{"name":"隧道","data":1,"date":"2020-01-09"},{"name":"隧道","data":16,"date":"2020-01-16"}],[{"name":"土方量","data":"","date":"2020-01-02"},{"name":"土方量","data":10,"date":"2020-01-09"},{"name":"土方量","data":45,"date":"2020-01-16"}]]
    var xAxisData = [];
    var legendData = [];
    var series = [];
    var oSeriesData = {};
    // 重组为echart可用格式
    for(var i=0; i<aSourceData.length; i++){  
        oSeriesData[aSourceData[i][0].name] = []
        for(var j=0; j<aSourceData[i].length; j++){
            if(i==0){
                xAxisData.push(aSourceData[i][j].date)
            }
            if(j==0){
                legendData.push(aSourceData[i][j].name)
            }
            oSeriesData[aSourceData[i][0].name].push(aSourceData[i][j].data)
        }
    }
    var option = {}
    option.legendData = legendData;
    option.xAxisData = xAxisData;
    option.series = fnSetSeires(oSeriesData)
    option.domname = 'echarts'
    fnSetOption(option)
}
function fnSetSeires(oSeriesData){
    var series = []
    for(var key in oSeriesData){
        var serie = {}
        serie.name = key;
        serie.type = 'line';
        serie.symbolSize = 10;
        serie.data = oSeriesData[key];
        series.push(serie);
    }
    return series
}
function fnSetOption(oData) {
    var option = {
        color: ['#c23531', '#61a0a8', '#6139a8', '#d48265', '#91c7ae', '#749f83', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'],
        title: {
        show: false,
        text: ''
        },
        tooltip: {
            trigger: 'axis',        
            formatter: function (params) {
            var relVal = params[0].name;
            for (var i = 0; i < params.length; i++) {
                relVal += '<br/>' + params[i].marker + params[i].seriesName + ' : ' + params[i].value + '%'
            }
            return relVal;
            }
        },
        legend: {
            textStyle:{
                color: '#ffffff'
            },
            data: []
        },
        grid: {
            top: '10%',
            left: '3%',
            right: '4%',
            bottom: '15%',
            containLabel: true
        },
        toolbox: {
            show: false,
            feature: {
                saveAsImage: {}
            }
        },
        xAxis: {
            type: 'category',
            boundaryGap: false,
            data: [],
            axisLine: {
                lineStyle: {
                    color: '#15b5cd'
                }
            },
            axisLabel: {
                color: '#ffffff',
                interval: 0,
                ritate: 40,
            }
        },
        yAxis: {
            type: 'value',
            max: 100,
            splitLine: {
            show: true,
            lineStyle: {
                color: 'rgba(255,255,255,0.2)'
            }
            },
            axisLine: {
                lineStyle: {
                    color: '#15b5cd'
                }
            },
            axisLabel: {
                color: '#ffffff',
                formatter:'{value}%'
            },
            
        },
        dataZoom: [{
            type: 'inside',
            textStyle: {
            color: '#fff'
            },
            start:0,
            end:100
        }, {
            type: 'slider',
            textStyle: {
            color: '#fff'
            }
        }],
        series: []
    }

    option.legend.data = oData.legendData;
    option.xAxis.data = oData.xAxisData;
    option.series = oData.series;

    var dom = document.getElementById(oData.domname);
    var echart = echarts.init(dom);
    echart.clear();
    echart.setOption(option,true);
}
fnCreateEchart()
<think>好的,用户想知道如何在ECharts中合并多个图表。根据引用[4],提到了多表共用一个滚动条的情况,这可能需要将多个图表联动起来。首先,我需要回忆ECharts的常见合并方法,比如使用grid配置调整位置或者使用多个坐标系。 然后,用户可能指的是在一个容器中同时显示多个图表,或者让它们共享某些组件,比如图例或工具栏。引用[2]和[3]提到了通用配置项如title、tooltip、toolbox,这些可以在单个option中设置,适用于多个图表。 另外,引用[5]提到options对自适应没影响,可能需要考虑布局的自适应处理。所以可能需要通过设置grid的不同参数来安排多个图表的位置。例如,调整每个图表的grid的top、left、right、bottom属性,使它们并排或上下排列。 还有一种情况是多个图表共享同一个数据或事件,比如点击一个图表影响另一个。这时候需要使用ECharts的事件监听和setOption方法更新其他图表数据。 需要检查是否有示例代码,但用户提供的引用中没有具体代码。可能需要根据官方文档,结合grid和多个series来实现。例如,在同一个option中配置多个series,并分配不同的grid区域,这样可以在一个实例中显示多个图表。或者使用多个ECharts实例,并通过事件进行联动。 最后,用户可能需要具体的步骤和代码示例,所以需要整理一个清晰的教程,分步骤说明如何通过配置grid或使用多个实例来合并图表,并引用相关的引用来源。</think>在ECharts中合并多个图表,主要通过**坐标系配置**和**组件复用**实现。以下是两种典型实现方式及完整示例: --- ### 方法一:单容器多坐标系布局 通过`grid`配置划分画布区域,结合`xAxisIndex/yAxisIndex`绑定坐标轴与数据系列 ```javascript const option = { // 通用标题配置(引用[3]标题配置) title: { text: '合并图表示例', left: 'center' }, // 划分两个上下排列的网格区域(引用[3]网格配置) grid: [ { top: '15%', height: '35%' }, // 上部区域 { top: '55%', height: '35%' } // 下部区域 ], // 共享X轴缩放组件(引用[4]滚动条联动) dataZoom: [{ type: 'slider', xAxisIndex: [0, 1], // 同时控制两个x轴 bottom: 10 }], // 第一个折线图配置 xAxis: [{ gridIndex: 0, data: ['周一','周二','周三'] }], yAxis: [{ gridIndex: 0 }], series: [{ type: 'line', data: [120, 200, 150], xAxisIndex: 0, yAxisIndex: 0 }], // 第二个柱状图配置 xAxis: [{ gridIndex: 1, data: ['A','B','C'] }], yAxis: [{ gridIndex: 1 }], series: [{ type: 'bar', data: [5, 20, 36], xAxisIndex: 1, yAxisIndex: 1 }] }; ``` --- ### 方法二:多实例联动 创建多个ECharts实例并通过事件监听实现交互联动 ```javascript // 初始化两个容器 const chart1 = echarts.init(document.getElementById('chart1')); const chart2 = echarts.init(document.getElementById('chart2')); // 配置数据轴同步(引用[4]多表联动) chart1.on('dataZoom', (params) => { const option = chart1.getOption(); chart2.setOption({ dataZoom: [{ startValue: option.dataZoom[0].startValue, endValue: option.dataZoom[0].endValue }] }); }); // 分别设置选项(引用[2]主题配置) chart1.setOption({ xAxis: { data: ['Q1','Q2','Q3'] }, series: [{ type: 'line', data: [65, 72, 83] }] }); chart2.setOption({ xAxis: { data: ['Q1','Q2','Q3'] }, series: [{ type: 'bar', data: [45, 68, 92] }] }); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值