关于前端:echarts实现多层不等距x轴支持框选缩放功能

54次阅读

共计 10893 个字符,预计需要花费 28 分钟才能阅读完成。

//————– 初始数据局部 ——————–
// 拼数据
let series: any = [];

// 寄存多层 x 轴数据的 series

const seriesextends: KeyValue[] = [];

// x 轴的层数
const xlevel: number = details[0].xaxisValue.length;
// 折线图的个数
const yAxisLineNum: number = details[0].yaxisLine.length;
// 柱型图的个数
const yAxisBarNum: number = details[0].yaxisBar.length;
// 最多的 x 的值
const xNum: number = details.length;
// lenged 中 data 的值
const yName: string[] = [];

// 初始化 yAxisLineListObject 的列表
let yAxisLineListObject = {

// yAxisLineValue1:['num1','num2','num3','num4']

};

for (let i: number = 0; i < yAxisLineNum; i++) {

const tempyaxislinevalue: string[] = [];
for (let j = 0; j < details.length; j++) {tempyaxislinevalue.push(details[j].yaxisLine[i].yvalue);
}
yAxisLineListObject = Object.assign({}, yAxisLineListObject, {[details[0].yaxisLine[i].yfield]: tempyaxislinevalue,
});

}
// console.log(yAxisLineListObject);

// 初始化 yAxisBarListObject 的列表
let yAxisBarListObject = {

// yAxisLineValue1:['num1','num2','num3','num4']

};
for (let i: number = 0; i < yAxisBarNum; i++) {

const tempyaxisbarvalue: string[] = [];
for (let j = 0; j < details.length; j++) {tempyaxisbarvalue.push(details[j].yaxisBar[i].yvalue);
}
yAxisBarListObject = Object.assign({}, yAxisBarListObject, {[details[0].yaxisBar[i].yfield]: tempyaxisbarvalue,
});

}
// console.log(yAxisBarListObject);

// 向 series 里填充 y 的折线图数据
for (let i: number = 0; i < Object.keys(yAxisLineListObject).length; i++) {

yName.push(Object.keys(yAxisLineListObject)[i]);
series.push({data: Object.values(yAxisLineListObject)[i],
  type: 'line',
  name: Object.keys(yAxisLineListObject)[i],
  yAxisIndex: 0,
  // xAxisIndex: 0,
});

}

// console.log(series);

// 向 series 里填充 y 的柱状图数据
for (let i: number = 0; i < Object.keys(yAxisBarListObject).length; i++) {

yName.push(Object.keys(yAxisBarListObject)[i]);
series.push({data: Object.values(yAxisBarListObject)[i],
  type: 'bar',
  name: Object.keys(yAxisBarListObject)[i],
  yAxisIndex: 1,
  // xAxisIndex: 1,
});

}

// 寄存所有层维度数据的数组
const xAxisArray: any = [];

// 先按维度的档次拼接 x 的名字
const tempxaxisname = [];
for (let i: number = 0; i < details.length; i++) {

const tempxaxislevelname: string[] = [];
tempxaxislevelname.push(details[i].xaxisValue[0]);
for (let j: number = 1; j < xlevel; j++) {
  tempxaxislevelname.push(tempxaxislevelname[j - 1] + ',' + details[i].xaxisValue[j],
  );
}
tempxaxisname.push(tempxaxislevelname);

}

// console.log(tempxaxisname, ‘ 按档次拼接好的 x 的名字 —————‘);

// 设置 x 轴的数据
const xAxisData: any = [

// {value: 星期 1}

];

for (let i: number = 0; i < details.length; i++) {

xAxisData.push({['value']: tempxaxisname[i][xlevel - 1],
  ['textStyle']: {['fontSize']: 8,
  },
});

}

// 分维度取出 x 轴的名字数组
for (let i: number = 0; i < xlevel; i++) {

let tempxxaisvalue: KeyValue = {};
// 该层循环确定一个维度上的名称和所占的单元格的长度
for (let j = 0; j < details.length; j++) {
  if (Object.keys(tempxxaisvalue)[Object.keys(tempxxaisvalue).length - 1] ===
    tempxaxisname[j][i]
  ) {
    // 如果和最初一位反复,则合并单元格,长度 +1

    // console.log("反复,须要合并");
    const lastkey =
      Object.keys(tempxxaisvalue)[Object.keys(tempxxaisvalue).length - 1];
    // console.log(lastkey);
    tempxxaisvalue[lastkey]++;
  } else {// console.log("不反复,不须要合并");

    tempxxaisvalue = Object.assign({}, tempxxaisvalue, {[tempxaxisname[j][i]]: 1,
    });
  }
}
xAxisArray.push(tempxxaisvalue);

}
// 外层循环走完所有的维度都曾经拼成了一个对象数组,对象外面别离包裹着每一层维度的名称和对应的长度,一个对象就是一个维度

// console.log(
// xAxisArray,
// ‘ 要给多层 x 轴进行渲染的 xAxisArray 对象数据 —————-‘,
// );

xAxisArray.reverse();

// 设置 grid 的值
const grid: any = [

{
  top: 100,
  bottom: (xlevel + 2) * 30,
},
{
  top: 100,
  bottom: (xlevel + 2) * 30,
},

];

// 设置多层的 x 轴,配置 series,grid,xAxis,yAxis
const xAxisExtends: any = [];
const yAxisExtends: any = [];
for (let i: number = 0; i < xlevel; i++) {

grid.push({
  height: 30,
  bottom: (xlevel - i + 1) * 30,
  tooltip: {// show: false,},
});
xAxisExtends.push({
  type: 'category',
  gridIndex: i + 2,
  axisLine: {show: false},
  axisLabel: {show: false},
  axisTick: {show: false},
});
yAxisExtends.push({
  type: 'value',
  gridIndex: i + 2,
  axisLine: {show: false},
  axisLabel: {show: false},
  axisTick: {show: false},
});
// 以后该维度的名字字符串和对应的所占单元格长度的字符串
const tempsingleXAxisName: string[] = Object.keys(xAxisArray[i]);
const tempsingleXAxisLength: number[] = Object.values(xAxisArray[i]);
// console.log(xAxisArray);

// 顺次填入该维度的所有呈现的名称与匹配的所占单元格的长度
for (let j: number = 0; j < Object.keys(xAxisArray[i]).length; j++) {
  // 设置填充进 bar 中的 name 的内容和款式,当长度大于以后 bar 的宽度时,以省略号显示
  let tempXAxisname: String = '';
  // tempsingleXAxisName[j].substring(tempsingleXAxisName[j].lastIndexOf(',')+1) 为要展现的全副的字符串
  if (tempsingleXAxisName[j].substring(tempsingleXAxisName[j].lastIndexOf(',') + 1,
    ).length >
    (tempsingleXAxisLength[j] / xNum) * 100 - 1
  )
    tempXAxisname =
      tempsingleXAxisName[j]
        .substring(tempsingleXAxisName[j].lastIndexOf(',') + 1)
        .substring(0, Math.floor((tempsingleXAxisLength[j] / xNum) * 100)) +
      '..';
  else
    tempXAxisname = tempsingleXAxisName[j].substring(tempsingleXAxisName[j].lastIndexOf(',') + 1,
    );

  seriesextends.push({
    type: 'bar',
    barWidth: (tempsingleXAxisLength[j] / xNum) * 100 + '%',
    data: [{name: tempXAxisname, value: 1}],
    barGap: 0,
    label: {
      show: true,
      position: 'inside',
      formatter: '{b}',
      // offset: [0, 10],
    },
    itemStyle: {
      color: 'none',
      borderColor: '#000',
      borderWidth: 1,
    },
    animation: false,
    tooltip: {formatter: tempsingleXAxisName[j].substring(tempsingleXAxisName[j].lastIndexOf(',') + 1,
      ),
    },
    // barWidth:
    xAxisIndex: i + 2,
    yAxisIndex: i + 2,
  });
}
// console.log(series,'+++++++++++');

}

//——————————————————————————————————————

//echarts 中 option 设置
let option: EChartsOption;



option = {
  title: {text: titleinfo,},

  tooltip: {
    trigger: 'item',
    axisPointer: {type: 'shadow',},
  },
  grid: grid,
  legend: {data: yName,},
  xAxis: [
    {
      type: 'category',
      data: xAxisData,
      position: 'bottom',
      gridIndex: 0,
      nameTextStyle: {fontSize: 8,},
      axisTick: {
        length: 30,
        interval: 0,
      },
     
      axisLabel: {show: false},
    },
    {
      type: 'category',
      gridIndex: 0,
      data: xAxisData,
      axisLine: {show: false},
      axisLabel: {show: false},
      axisTick: {show: false},
    },

    // 上面都是多的 x 轴

    ...xAxisExtends,
  ],

  yAxis: [
    {
      type: 'value',
      name: '折线图数据',
      gridIndex: 0,
      min: 'dataMin',
      axisLabel: {formatter: function (value: number) {// console.log(value,'y 轴的值');
          // console.log(value.toExponential(2),'解决后的 y 轴的值');

          return value.toExponential(1);
        },
      },
    },
    {
      type: 'value',
      name: '柱形图数据',
      gridIndex: 0,
      position: 'right',
      max: 'dataMax',
      min: 'dataMin',
      axisLabel: {formatter: function (value: number) {// console.log(value,'y 轴的值');
          // console.log(value.toExponential(2),'解决后的 y 轴的值');

          return value.toExponential(1);
        },
      },
    },

    // 上面都是多的 y 轴
    ...yAxisExtends,
  ],

  series: [...series, ...seriesextends],

  toolbox: [
    {
      feature: {
        dataZoom: {
          show: true,
          // type: ['zoom'],
          yAxisIndex: false,
          xAxisIndex: 0,
        },
      },
      // right:-25
    },
  ],
};

//———————————————————————————————————————————————————

// 缩放的监听,管制多层 x 轴的变动
myChart.on(‘datazoom’, (params: any) => {

  // console.log(xAxisData, 'on 监听外面的 xAxisData----------');
  let slicestart: number = 0;
  let sliceend: number = 0;
  // 回退到最初始的状态时
  if (params.batch[0].start === 0) {
    slicestart = 0;
    sliceend = details.length - 1;
  }
  // 有 startValue 值的时候(惯例缩放)else if (params.batch[0].startValue) {slicestart = params.batch[0].startValue;
    sliceend = params.batch[0].endValue;
  }

  setdatazoom(slicestart, sliceend);
});

function setdatazoom(slicestart: number, sliceend: number) {

  
  const slicelength: number = sliceend - slicestart + 1;
  // 缩放之后的 x 轴的更新的 data
  const sliceXAXisData = xAxisData.slice(slicestart, sliceend + 1);
  // console.log(
  //   sliceXAXisData,
  //   'sliceXAXisData+++++ 缩放时候的 x 轴的 data 数据 +',
  // );
 

  
  
  // 寄存所有层维度数据的数组
  const slicexAxisArray: any = [];

  // 先按维度的档次拼接 x 的名字
  const slicetempxaxisname = [];
  for (let i: number = slicestart; i < sliceend + 1; i++) {const tempxaxislevelname: string[] = [];
    tempxaxislevelname.push(details[i].xaxisValue[0]);
    for (let j: number = 1; j < xlevel; j++) {
      tempxaxislevelname.push(tempxaxislevelname[j - 1] + ',' + details[i].xaxisValue[j],
      );
    }
    slicetempxaxisname.push(tempxaxislevelname);
  }

  // console.log(
  //   slicetempxaxisname,
  //   '缩放后按档次拼接好的 x 的名字 ---------------',
  // );

  // 分维度取出 x 轴的名字数组
  for (let i: number = 0; i < xlevel; i++) {let tempxxaisvalue: KeyValue = {};
    // 该层循环确定一个维度上的名称和所占的单元格的长度
    for (let j: number = 0; j < slicetempxaxisname.length; j++) {
      if (Object.keys(tempxxaisvalue)[Object.keys(tempxxaisvalue).length - 1
        ] === slicetempxaxisname[j][i]
      ) {
        // 如果和最初一位反复,则合并单元格,长度 +1

        // console.log("反复,须要合并");
        const lastkey =
          Object.keys(tempxxaisvalue)[Object.keys(tempxxaisvalue).length - 1
          ];
        // console.log(lastkey);
        tempxxaisvalue[lastkey]++;
      } else {// console.log("不反复,不须要合并");

        tempxxaisvalue = Object.assign({}, tempxxaisvalue, {[slicetempxaxisname[j][i]]: 1,
        });
      }
    }
    slicexAxisArray.push(tempxxaisvalue);
  }
  //    外层循环走完所有的维度都曾经拼成了一个对象数组,对象外面别离包裹着每一层维度的名称和对应的长度,一个对象就是一个维度

  // console.log(
  //   slicexAxisArray,
  //   '缩放时要给多层 x 轴进行渲染的 xAxisArray 对象数据 ----------------',
  // );

  slicexAxisArray.reverse();

  const sliceseriesextends = [];

  for (let i: number = 0; i < xlevel; i++) {
    // 以后该维度的名字字符串和对应的所占单元格长度的字符串
    const slicetempsingleXAxisName: string[] = Object.keys(slicexAxisArray[i],
    );
    const slicetempsingleXAxisLength: number[] = Object.values(slicexAxisArray[i],
    );
    // console.log(slicetempsingleXAxisName,'datazoomtempsingleXAxisName..................');
    // console.log(slicetempsingleXAxisLength,'datazoomtempsingleXAxisLength..................');

    // 顺次填入该维度的所有呈现的名称与匹配的所占单元格的长度
    for (
      let j: number = 0;
      j < Object.keys(slicexAxisArray[i]).length;
      j++
    ) {
      // 设置填充进 bar 中的 name 的内容和款式,当长度大于以后 bar 的宽度时,以省略号显示
      let slicetempXAxisname: String = '';
      //slicetempsingleXAxisName[j].substring(slicetempsingleXAxisName[j].lastIndexOf(',')+1) 为要展现的全副的字符串
      if (slicetempsingleXAxisName[j].substring(slicetempsingleXAxisName[j].lastIndexOf(',') + 1,
        ).length >
        (slicetempsingleXAxisLength[j] / slicelength) * 100 - 1
      ) {
        slicetempXAxisname =
          slicetempsingleXAxisName[j]
            .substring(slicetempsingleXAxisName[j].lastIndexOf(',') + 1)
            .substring(
              0,
              Math.floor((slicetempsingleXAxisLength[j] / slicelength) * 100,
              ),
            ) + '..';
      } else
        slicetempXAxisname = slicetempsingleXAxisName[j].substring(slicetempsingleXAxisName[j].lastIndexOf(',') + 1,
        );

      sliceseriesextends.push({
        type: 'bar',
        barWidth: (slicetempsingleXAxisLength[j] / slicelength) * 100 + '%',
        data: [{name: slicetempXAxisname, value: 1}],
        barGap: 0,
        label: {
          show: true,
          position: 'inside',
          formatter: '{b}',
          // offset: [0, 10],
        },
        itemStyle: {
          color: 'none',
          borderColor: '#000',
          borderWidth: 1,
        },
        animation: false,
        tooltip: {formatter: slicetempsingleXAxisName[j].substring(slicetempsingleXAxisName[j].lastIndexOf(',') + 1,
          ),
        },
        // barWidth:
        xAxisIndex: i + 2,
        yAxisIndex: i + 2,
      });
    }
  }
  // console.log(sliceseriesextends, 'sliceseriesextends+++++++++++');

  

  myChart.setOption(
    {series: [...series, ...sliceseriesextends],
      yAxis: [
        {
          type: 'value',
          name: '折线图数据',
          gridIndex: 0,
          min: 'dataMin',
          max: 'dataMax',
          axisLabel: {formatter: function (value: number) {// console.log(value,'y 轴的值');
              // console.log(value.toExponential(2),'解决后的 y 轴的值');

              return value.toExponential(1);
            },
          },
        },
        {
          type: 'value',
          name: '柱形图数据',
          gridIndex: 0,
          position: 'right',
          max: 'dataMax',
          min: 'dataMin',
          axisLabel: {formatter: function (value: number) {// console.log(value,'y 轴的值');
              // console.log(value.toExponential(2),'解决后的 y 轴的值');

              return value.toExponential(1);
            },
          },
        },

        // 上面都是多的 y 轴
        ...yAxisExtends,
      ],

      
    },
    {replaceMerge: ['series', 'yAxis'], // 替换合并 series,默认一般合并
    },
  );
}

//———————————————————————————————————————————————————————————-
// 原始数据 details 的格局
details: [

    {
      yaxisBar: [
        {
          yfield: 'firstPassCPU',
          yvalue: '1E-14',
        },
        {
          yfield: 'firstPassCPK',
          yvalue: '-1E-14',
        },
      ],
      yaxisLine: [
        {
          yfield: 'firstPassCP',
          yvalue: '0',
        },
      ],
      xaxisValue: [
        '20211023',
        'AGD142M208-D001',
        '1000:GSM824_Idle_Current',
      ],
    },
    {
      yaxisBar: [
        {
          yfield: 'firstPassCPU',
          yvalue: '8E-15',
        },
        {
          yfield: 'firstPassCPK',
          yvalue: '-8E-15',
        },
      ],
      yaxisLine: [
        {
          yfield: 'firstPassCP',
          yvalue: '0',
        },
      ],
      xaxisValue: [
        '20211023',
        'AGD142M208-D001',
        '1001:GSM824_Max_Pout_0dBm_Drive',
      ],
    },

}

正文完
 0