//--------------初始数据部分--------------------
// 拼数据
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 = https://www.it610.com/article/{};
// 该层循环确定一个维度上的名称和所占的单元格的长度
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 = https://www.it610.com/article/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 = https://www.it610.com/article/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 = https://www.it610.com/article/{};
// 该层循环确定一个维度上的名称和所占的单元格的长度
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 = https://www.it610.com/article/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',
],
},
【echarts实现多层不等距x轴,支持框选缩放功能】}