Echart双Y轴刻度对齐

4/12/2023 Echart

# 前情回顾


推荐这篇优秀的文章:
EchartJS 双Y轴 0刻度对齐处理

文章中介绍了Echart双轴出现负值时双轴对称处理方式,最后能达到0刻度线对其,但是双轴每段刻度参差不齐。

抛开技术不谈,就美观程度来说还是不够的。

遂有一个新需求诞生:需要达到 刻度对齐

# 刻度对齐


刻度对其相对来说没那么麻烦,通过Echart提供的API即可达到效果。

interval:强制设置坐标轴分割间隔
max:坐标轴刻度最大值。

重点是计算每段坐标轴分割间隔大小。

算法逻辑是先缩小每段刻度的10^n,再向上取整,最后放大回来。

比如:

    当每段为241.28571428571428
    Math.ceil(241.28571428571428 / 100) * 100 = 300

    当每段为81691.42857142857
    Math.ceil(81691.42857142857 / 1000) * 1000 = 82000
		// 数据
		var LeftNum = [0, 1336, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, ]
		var LeftNum = [503, 1689, 118, 165, 686, 662, 645, 320, 15, 113, 40, 143, 740, 182, 29];

		var LeftData = {
			max: Math.max(...LeftNum),
			min: Math.min(...LeftNum)
		}
		var RightNum = [571840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
		RightNum = [2, 0, 6, 2, 2, 3, 11, 6, 7, 4, 1, 2, 1, 6, 7];

		var RightData = {
			max: Math.max(...RightNum),
			min: Math.min(...RightNum)
		}

		//双轴段数
		let intervalData = 7;

		console.group("双轴取整后每段大小");
		let yAxisIntervalList = [IntergerNode(LeftData.max / intervalData), IntergerNode(RightData.max / intervalData)];
		console.log("双轴取整后每段大小", yAxisIntervalList)
		console.groupEnd();

		console.group("双轴最大值");
		let yAxisMaxList = [yAxisIntervalList[0] * intervalData, yAxisIntervalList[1] * intervalData];
		console.log("双轴最大值", yAxisMaxList)
		console.groupEnd();

		// 选中项
		var selected = {
			注册: true,
			活跃: true
		}

		var dom = document.getElementById("container");
		var myChart = echarts.init(dom);
		var app = {};
		option = null;

		option = {
			//1、 格式化提示信息
			tooltip: {
				trigger: 'axis',
			},
			toolbox: {
				feature: {
					dataView: {
						show: true,
						readOnly: false
					},
					magicType: {
						show: true,
						type: ['line', 'bar']
					},
					restore: {
						show: true
					},
					saveAsImage: {
						show: true
					}
				}
			},
			legend: {
				data: ['注册', '活跃'],
				selected,
			},
			grid: {
				width: '50%',
				height: '50%'
			},
			xAxis: [{
				type: 'category',
				data: [
					"2022-09-01",
					"2022-09-02",
					"2022-09-03",
					"2022-09-04",
					"2022-09-05",
					"2022-09-06",
					"2022-09-07",
					"2022-09-08",
					"2022-09-09",
					"2022-09-10",
					"2022-09-11",
					"2022-09-12",
					"2022-09-13",
					"2022-09-14"
				],
				axisPointer: {
					type: 'shadow'
				}
			}],
			yAxis: [{
					type: 'value',
					name: '注册',
					interval: yAxisIntervalList[0],
					max: yAxisMaxList[0],
				},
				{
					type: 'value',
					name: '活跃',
					interval: yAxisIntervalList[1],
					max: yAxisMaxList[1],
				}
			],
			series: [{
					name: '注册',
					type: 'bar',
					data: LeftNum
				},
				{
					name: '活跃',
					type: 'bar',
					yAxisIndex: 1,
					data: RightNum
				},

			]
		};

		if (option && typeof option === "object") {
			myChart.setOption(option, true);
			myChart.on('legendselectchanged', function(params) {
				option.legend.selected = params.selected
				selected = params.selected
				myChart.setOption(option);
			})
		}

		function IntergerNode(data) {
			console.group(`节点取整计算:${data}`)
			data = data < 0 ? Math.abs(data) : data;
			// 数值位数
			let len = parseInt(data).toString().length;
			console.log("长度", len)
			if (len <= 2) {
				let value = Math.ceil(data)
				console.log("长度 < 2,直接取整", value)
				return value;
			}
			// 缩放倍数系数
			let coefficient = len >= 4 ? 2 : 1
			// 缩小倍数
			let multiple = Math.pow(10, len - coefficient);
			console.log(`倍数系数 10^${coefficient}`, )
			// 缩小N倍,向上取整,放大N倍
			let value = Math.ceil(data / multiple) * multiple;
			value = data < 0 ? -value : value;
			console.log(`取整结果 Math.ceil(${data} / ${multiple}) * ${multiple} = ${value}`);
			console.groupEnd()
			return value;
		}

每段坐标轴分割间隔大小

# 总结


上面只能应对数据都是正数的情况。如果数据中有负数就会出现0刻度不对其的情况。
暂时能想到的,能解决负数的办法是 镜像正区间部分到负区间-实现0刻度线对齐
在美观性上还是有所欠缺。😅😅😅

# 思考一


按照常理来说 双轴刻度对其 0刻度对其 也算是一个常规需求。
但是市面上的的图表组件好像都没这个效果,难道不好实现?

# 思考二


"魔鬼"客户又又又提了个新需求:
假设图表X轴显示了30天的数据1号~30号,正常图表中X轴是放不下所有时间的,会以省略的方式显示。
对方希望起止日期正常显示,中间部分可以省略显示。市面上也没有这种组件。😅😅😅

Last Updated: 9/2/2023, 11:23:17 AM