双x轴不等分情况实现思路:
- 一个网格为常规图,常规x轴作为子级;
- 另一个网格绘制柱状图,每根柱子就是一个父级,设置柱子的宽度(子级数占总数的百分比)即可。
代码:
const baseData = [
{
value: '贵阳市',
children: [
{ value: '花溪区', num: 1, count: 12 },
{ value: '南明区', num: 15, count: 23 },
{ value: '观山湖区', num: 18, count: 42 }
],
regionColor: '#F4BBB8'
},
{
value: '六盘水市',
children: [
{ value: '钟山区', num: 25, count: 35 },
{ value: '六枝特区', num: 23, count: 32 }
],
regionColor: '#FFD1AF'
},
{
value: '遵义市',
children: [
{ value: '红花岗区', num: 32, count: 52 },
{ value: '汇川区', num: 33, count: 42 },
{ value: '遵义县', num: 36, count: 62 }
],
regionColor: '#F3EFA3'
},
{
value: '安顺市',
children: [
{ value: '西秀区', num: 57, count: 52 },
{ value: '平坝县', num: 72, count: 62 }
],
regionColor: '#D8D4EC'
},
{
value: '铜仁市',
children: [{ value: '玉屏县', num: 45, count: 42 }],
regionColor: '#B1CEF8'
}
];
const dLength = baseData
.map((item) => item.children.length)
.reduce((n, m) => n + m); // x轴数据总长度,用于计算父级x轴的宽度
let xData = [];
let yData1 = [];
let yData2 = [];
let series = [
{
name: '销量',
data: yData1,
type: 'line',
label: {
show: true,
position: 'top',
textStyle: {
color: '#555'
}
},
xAxisIndex: 0,
yAxisIndex: 0,
},
{
name: '库存',
data: yData2,
type: 'line',
label: {
show: true,
position: 'top',
textStyle: {
color: '#555'
}
},
xAxisIndex: 0,
yAxisIndex: 0
}
];
// 不同等份分区域
let baseObj = {
data: [
{
name: '',
value: 1
}
],
label: {
show: true,
position: 'inside',
formatter: '{b}',
offset: [0, 2],
textStyle: {
color: '#666'
}
},
type: 'bar',
barGap: 0,
barWidth: '',
itemStyle: {
color: '',
opacity: 0.8
},
animationEasing: 'bounceOut',
xAxisIndex: 1,
yAxisIndex: 1
};
baseData.forEach((item, index) => {
let pObj = JSON.parse(JSON.stringify(baseObj));
pObj.data[0].name = item.value;
pObj.barWidth = (item.children.length / dLength) * 100 + '%';
pObj.itemStyle.color = item.regionColor;
series.push(pObj);
item.children.forEach((cItem) => {
xData.push({
value: cItem.value,
pName: item.value,
regionColor: item.regionColor
});
yData1.push(cItem.num);
yData2.push(cItem.count);
});
});
myChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter(params) {
let str = '';
baseData.forEach((item, index) => {
item.children.forEach((cItem) => {
if (cItem.value == params[0].name) {
str = item.value + '<br/>' + params[0].name + '<br/>';
}
});
});
for (let item of params) {
//设置浮层图形的样式跟随图中展示的颜色
str +=
"<span style='display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:10px;background-color:" +
item.color +
";'></span>" +
item.seriesName +
' : ' +
item.value+'<br/>';
}
return str;
}
},
legend: { data: ['销量', '库存'] },
grid: [
{
top: 100,
bottom: 100
},
{
height: 20,
bottom: 100,
tooltip: { show: false }
}
],
dataZoom: {
type: 'slider'
},
xAxis: [
{
type: 'category',
data: xData,
gridIndex: 0,
axisLabel: {
color: '#333'
},
axisLine: {
lineStyle: {
color: '#e7e7e7'
}
},
axisTick: {
lineStyle: {
color: '#e7e7e7'
}
},
zlevel: 2
},
{
type: 'category',
gridIndex: 1,
axisLine: { show: false },
axisLabel: { show: false },
axisTick: { show: false },
zlevel: 1
}
],
yAxis: [
{
type: 'value',
gridIndex: 0,
axisLabel: {
color: '#333'
},
splitLine: {
lineStyle: {
type: 'dashed'
}
},
axisLine: {
lineStyle: {
color: '#ccc'
}
},
axisTick: {
lineStyle: {
color: '#ccc'
}
}
},
{
type: 'value',
gridIndex: 1,
axisLabel: { show: false },
axisLine: { show: false },
splitLine: { show: false },
axisTick: { show: false }
}
],
series
});
// dataZoom缩放事件
myChart.on('dataZoom', (params) => {
const dataZoom = myChart.getModel().option.dataZoom[0];
const { startValue, endValue } = dataZoom;
let curXdata = xData.slice(startValue, endValue + 1); // 缩放后的子级
let curPdata = [...new Set(curXdata.map((item) => item.pName))]; // 取出父级去重
series.length = 2; // 默认初始值
curPdata.forEach((item, index) => {
let length = 0;
let regionColor = '';
curXdata.forEach((cItem) => {
if (cItem.pName === item) {
length++;
regionColor = cItem.regionColor;
}
});
let pObj = JSON.parse(JSON.stringify(baseObj));
pObj.data[0].name = item;
pObj.barWidth = (length / curXdata.length) * 100 + '%';
pObj.itemStyle.color = regionColor;
series.push(pObj);
});
myChart.setOption(
{
series
},
{
replaceMerge: 'series' // 替换合并series,默认普通合并
}
);
});
最终效果: