<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>echarts自定义分组-动态</title>
<script src="echarts4.js"></script>
</head>
<body>
<div id="bar" style="width: 800px; height: 600px;"></div>
<script type="text/javascript">
// 转化成echarts参数,
// data: 数据,levels: 分几组,tickLength:刻度线的长度(标签多高)
function toEchartsOption(data, levels, tickLength) {
// 如果分组不在正中间,需要加上偏移宽度
var labelOffset = "{offset|}";
var xAxis = [];
var seriesData = [];
var option = {
title: {
text: 'echarts自定义分组-动态'
}
, xAxis: xAxis
, yAxis: {}
, series: [{type: 'bar', data: seriesData}]
, dataZoom: [
{ // 这个dataZoom组件,默认控制x轴。
type: 'slider', // 这个 dataZoom 组件是 slider 型 dataZoom 组件
xAxisIndex: [],
start: 0,
end: 30 // 右边在 60% 的位置。
}
],
};
for (var i = 0; i < levels; i++) {
option.dataZoom[0].xAxisIndex.push(i); // 填充datazoom的联动
}
// 度量数据
for (var i = 0; i < data.length; i++) {
seriesData.push(data[i][levels]);
}
// 标签的初始边距,随着分层递增
var labelMargin = 10;
// 构造xAxis数据
for (var lvl = levels - 1; lvl >=0; lvl--) {
var xAxisData = [];
var xAxisItem = {
position: "bottom"
, data: xAxisData
, axisTick: {
length: tickLength * (levels - lvl)
}
, axisLabel: {
interval : 0, // 显示所有标签
margin: labelMargin + tickLength * (levels - lvl - 1)
}
};
if (lvl == levels - 1) {
// 最后一级不做任何合并处理
for (var i = 0; i < data.length; i++) {
xAxisData.push(data[i][lvl]);
}
} else {
// 分组级,做分隔线和合并处理
var tickSeparates = [];
var prevData = ""; // 上一组的数据
var prevDataNum = 1; // 上一组的数据条目
for (var i = 0; i < data.length; i++) {
var lvlData = data[i][lvl];
xAxisData.push("");
if (lvlData != prevData) {
// 加分隔线
tickSeparates.push(true);
if (i > 0) {
// 对上一组数据进行处理
if (prevDataNum%2 == 0) {
// 偶数,放在中间靠前的位置,需要偏移
xAxisData[i - parseInt(prevDataNum/2) - 1] = labelOffset + prevData;
} else {
// 奇数,直接放正中间,不需要偏移
xAxisData[i - parseInt(prevDataNum/2) - 1] = prevData;
}
}
prevDataNum = 1;
} else {
tickSeparates.push(false);
prevDataNum++;
}
prevData = lvlData;
}
if (prevDataNum%2 == 0) {
// 偶数,放在中间靠前的位置,需要偏移
xAxisData[xAxisData.length - parseInt(prevDataNum/2) - 1] = labelOffset + prevData;
} else {
// 奇数,直接放正中间,不需要偏移
xAxisData[xAxisData.length - parseInt(prevDataNum/2) - 1] = prevData;
}
// 根据分隔标识画分隔线
xAxisItem.axisTick.interval = ((tickSeparates) => {
return (index, value) => {
return tickSeparates[index];
};
})(tickSeparates);
// 指定偏移的自定义样式,初始偏移为0
xAxisItem.axisLabel.rich = {
offset: {
width: 0
}
}
}
xAxis.push(xAxisItem);
}
return option;
}
//数据
var data = [
["湖北", "武汉市", "江岸区", 180]
, ["湖北", "武汉市", "江汉区", 200]
, ["湖北", "黄石市", "黄石港区", 130]
, ["湖北", "黄石市", "西塞山区", 100]
, ["湖北", "宜昌市", "夷陵区", 90]
, ["湖南", "长沙市", "芙蓉区", 120]
, ["湖南", "长沙市", "天心区", 110]
, ["湖南", "株洲市", "天元区", 80]
, ["广东", "广州市", "越秀区", 120]
, ["广东", "广州市", "荔湾区", 150]
, ["广东", "广州市", "增城区", 100]
];
// 三级
var levels = 3;
// echarts实例
var chart = echarts.init(document.getElementById('bar'));
var option = toEchartsOption(data, levels, 20);
chart.lastBandWidth = 0;
// 监听渲染事件,只要bandWidth发生变化,重新设置标签偏移的值
chart.on('rendered', function () {
var bandWidth = chart._chartsViews[0].renderTask.context.outputData._layout.bandWidth;
if (chart.lastBandWidth != bandWidth) {
chart.lastBandWidth = bandWidth;
// 延时执行否则echarts渲染异常
setTimeout(()=>{
// 加上偏移后重新绘制
var optionNew = {xAxis: [{}]};
for (var i = 1; i < levels; i++) {
// 增量更新偏移值
optionNew.xAxis.push({axisLabel:{rich:{offset:{width: chart.lastBandWidth}}}});
}
//console.info(optionNew);
chart.setOption(optionNew);
}, 0);
}
});
// 先绘制第一遍,找到绘制后每个柱子的刻度宽度
chart.setOption(option);
</script>
</body>
</html>
评论0