Echarts 实现不等分双X轴

Echarts 双X轴只支持在等分的情况,这里写一个实现不等分的思路

demo

实现思路:

  1. 两个网格 grid,绘制两组柱图;
  2. 一个网格为常规柱图,常规x轴作为子级;
  3. 另一个网格绘制父级柱图,通过计算设置柱子的宽度(子级数占总数的百分比),以实现父级效果
  • 2021-12-06更新 支持区域缩放
const baseData = [{
		value: '贵阳市',
		children: [
			{ value: '花溪区', num: 0.1 },
			{ value: '南明区', num: 0.15 },
			{ value: '观山湖区', num: 0.18 }
		]
	},{
		value: '六盘水市',
		children: [
			{ value: '钟山区', num: 0.25 },
			{ value: '六枝特区', num: 0.23 }
		]
	},{
		value: '遵义市',
		children: [
			{ value: '红花岗区', num: 0.32 },
			{ value: '汇川区', num: 0.33 },
			{ value: '遵义县', num: 0.36 }
		]
	},{
		value: '安顺市',
		children: [
			{ value: '西秀区', num: 0.57 },
			{ value: '平坝县', num: 0.72 }
		]
	},{
		value: '铜仁市',
		children: [
			{ value: '玉屏县', num: 0.45 }
		]
}]
const dLength = baseData.map(item => item.children.length).reduce((n, m) => n + m) // x轴数据总长度,用于计算父级x轴的宽度
let xData = []
let yData = []
let series = [{
	data: yData,
	type: 'bar',
	label: {
		show: true,
		position: 'top',
		textStyle: {
			color: '#555'
		}
	},
	itemStyle: {
		color: (params) => {
			return colorBg(params.dataIndex)
		}
	},
	xAxisIndex: 0,
	yAxisIndex: 0
}]
let baseObj = {
	data: [{
		name: '',
		value: 1
	}],
	label: {
		show: true,
		position: 'inside',
		formatter: '{b}',
		offset: [0, 10],
		textStyle: {
			color: '#666'
		}
	},
	type: 'bar',
	barGap: 0,
	barWidth: '',
	itemStyle: {
		color: '',
		opacity: .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 = colorBg(index)
	series.push(pObj)
	item.children.forEach(cItem => {
		xData.push({
			value: cItem.value,
			pName: item.value
		})
		yData.push(cItem.num)
	})
})

function colorBg(index) {
	const colors = ['#4150d8', '#28bf7e', '#ed7c2f', '#f2a93b', '#f9cf36', '#4a5bdc', '#4cd698', '#f4914e', '#fcb75b', '#ffe180', '#b6c2ff', '#96edc1']
	return colors[index]
}

myChart.setOption({
	tooltip: {
		trigger: 'axis',
		axisPointer: {
			type: 'shadow'
		}
	},
	grid: [{
			top: 100,
			bottom: 111
		},{
			height: 60,
			bottom: 50,
			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 = 1 // 
	curPdata.forEach((item, index) => {
		let length = 0
		curXdata.forEach(cItem => {
			if (cItem.pName === item) {
				length++
			}
		})
		let pObj = JSON.parse(JSON.stringify(baseObj))
		pObj.data[0].name = item
		pObj.barWidth = length / curXdata.length * 100 + '%'
		pObj.itemStyle.color = colorBg(index)
		series.push(pObj)
	})
	myChart.setOption({
		series
	}, {
		replaceMerge: 'series', // 替换合并series,默认普通合并
	})
})
  • 2023-08-02更新 优化区域缩放后,父级背景颜色不重置
    修改以下部分代码
// 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 = 1 // 保留子级
	curPdata.forEach((item, index) => {
		let length = 0
		curXdata.forEach(cItem => {
			if (cItem.pName === item) {
				length++
			}
		})
		let pObj = JSON.parse(JSON.stringify(baseObj))
		pObj.data[0].name = item
		pObj.barWidth = length / curXdata.length * 100 + '%'
		const pIndex = baseData.findIndex(bItem => bItem.value === item)
		pObj.itemStyle.color = colorBg(pIndex)
		series.push(pObj)
	})
	myChart.setOption({
		series
	}, {
		replaceMerge: 'series', // 替换合并series,默认普通合并
	})
})

在这里插入图片描述

  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
可以通过Echarts的grid、xAxis和yAxis属性配置实现x非等分的情况,具体步骤如下: 1. 在grid属性中设置bottom、top、left、right属性,控制图表的位置和大小。 2. 在xAxis属性中设置type为'category',设置data属性为x要展示的数据,同时设置axisTick、axisLabel、splitLine等属性。 3. 在yAxis属性中设置type为'value',设置axisTick、axisLabel、splitLine等属性。 4. 在series属性中设置type为'bar',同时设置xAxisIndex属性为0或1,控制柱状图在哪个x上展示。 5. 如果需要让两个x的刻度对应起来,可以设置grid属性中的height、width属性和yAxis属性中的max、min属性,使得两个x的刻度对应。 以下是一个示例代码: ```javascript option = { grid: { top: 50, left: 50, right: 50, bottom: 80, height: 200, width: '80%' }, xAxis: [{ type: 'category', data: ['A', 'B', 'C', 'D', 'E'], axisTick: { alignWithLabel: true }, axisLabel: { interval: 0 }, splitLine: { show: false } }, { type: 'category', data: ['F', 'G', 'H', 'I', 'J'], axisTick: { alignWithLabel: true }, axisLabel: { interval: 0 }, splitLine: { show: false } }], yAxis: { type: 'value', axisTick: { show: false }, axisLabel: { formatter: '{value} $' }, splitLine: { lineStyle: { type: 'dashed' } } }, series: [{ name: 'Series 1', type: 'bar', data: [10, 20, 30, 40, 50], xAxisIndex: 0 }, { name: 'Series 2', type: 'bar', data: [60, 70, 80, 90, 100], xAxisIndex: 1 }] }; ``` 以上代码实现x非等分的柱状图,其中第一个x显示A到E,第二个x显示F到J,两个x的刻度对应,同时图表通过grid属性控制了位置和大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZionHH

落魄前端,在线炒粉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值