EchartJS 双Y轴 0刻度对齐处理
Hz 9/23/2022 Echart
# 奇怪需求
Echart双Y轴,如果数据中包含负数,就会出现0刻度不对其的情况。
现客户希望能做到0刻度线对齐。因为Excel能做到。😀
按理来说,这应该算一个常规需求,可Echart并没有相关API参数。
# 镜像 正区间部分,实现0刻度线对齐
通过镜像处理的方式,也就是把双轴中的最大值,分别设置到Min Max中。
就可以完成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 = [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)
}
console.log(LeftData)
console.log(RightData)
// 选中项
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-08-31",
"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: '注册',
max: function(value) {
if (Math.abs(value.max) > Math.abs(value.min)) {
return (Math.abs(value.max)).toFixed(2);
} else {
return (Math.abs(value.min)).toFixed(2);
}
},
min: function(value) {
if (Math.abs(value.max) > Math.abs(value.min)) {
return (-Math.abs(value.max)).toFixed(2);
} else {
return (-Math.abs(value.min)).toFixed(2);
}
}
},
{
type: 'value',
name: '活跃',
max: function(value) {
if (Math.abs(value.max) > Math.abs(value.min)) {
return (Math.abs(value.max)).toFixed(2);
} else {
return (Math.abs(value.min)).toFixed(2);
}
},
min: function(value) {
if (Math.abs(value.max) > Math.abs(value.min)) {
return (-Math.abs(value.max)).toFixed(2);
} else {
return (-Math.abs(value.min)).toFixed(2);
}
}
}
],
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);
})
}
# 通过比例计算最小值
通过镜像正区间的方式,能实现效果,但是不尽如意。下方留白会过多
从上图中分析可以知道:
- 1.正区间双轴最大值可以从数据中算出
- 2.负区间双轴最大值也是可以算出来的
- 3.只有负区间的较小值需要通过比例计算
通过列方程简化后可解得:min1 = max1 * min2 / max2
- min1 max1 表示负区间中的较小值的轴,图中右轴
- min2 max2 表示负区间中的较大值的轴,图中左轴
注:不要去 format 计算出来的数据,不然会出现对不齐(悬空、挤出)等情况。可以用 yAxis.axisLabel.formatter 处理展示内容。
// 数据
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]
//var 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)
}
console.log(LeftData)
console.log(RightData)
// 选中项
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: '注册',
min: function(value) {
let t = Min(value, 'left')
console.log("Left", t);
return t;
},
max: function(value) {
return Max(value)
}
},
{
type: 'value',
name: '活跃',
min: function(value) {
let t = Min(value, 'right')
console.log("Right", t);
return t;
},
max: function(value) {
return Max(value)
}
}
],
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 Min(value, direction) {
if (LeftData.min >= 0 && RightData.min >= 0) {
return 0;
}
if (direction === 'left') {
if (Math.abs(LeftData.min) > Math.abs(RightData.min)) {
if(LeftData.min > 0) return 0;
return LeftData.min;
} else {
if (RightData.max === 0) {
return -Math.abs(LeftData.max)
}
// max1 * min2 / max2
let t = LeftData.max * RightData.min / RightData.max;
return t; // 不要 format 数据,不然会出现对不齐的情况
}
}
if (direction === 'right') {
if (Math.abs(RightData.min) > Math.abs(LeftData.min)) {
return RightData.min;
} else {
if (LeftData.max === 0) {
return -Math.abs(RightData.max)
}
// max1 * min2 / max2
let t = RightData.max * LeftData.min / LeftData.max;
if(t > 0) return 0;
return t; // 不要 format 数据,不然会出现对不齐的情况
}
}
}
function Max(value) {
console.log("MAX", value);
if (value.max === 0) {
return Math.abs(value.min)
}
return value.max;
}
# 最后
学好数学是很重要滴!😀