假如提供了一份示例数据:
let data = {
2011: 264,
2012: 352,
2013: 256,
2014: 368,
2015: 189,
2016: 98,
2017: 643,
2018: 259,
2019: 365,
2020: 521,
};
我们通过Echarts提供的柱状图、时间轴组件简单地把数据展示出来:
let xData = [];
let yData = [];
for (let key in data) {
xData.push(key);
yData.push(data[key]);
}
let chartEl = document.getElementById("timeline");
let chart = echarts.init(chartEl);
let option = {
timeline: {
data: xData,
axisType: "category",
show: true,
autoPlay: true,
playInterval: 2000,
bottom: 20,
symbol: "emptyCircle",
symbolSize: 5,
color: "#0088cc",
checkpointStyle: {
symbolSize: 8,
color: "#0088cc",
borderColor: "rgba(0,136,204,0.5)"
},
controlStyle: {
emphasis: {
color: "#176FCC",
borderColor: "#176FCC"
}
},
label: {
normal: {
show: true
}
}
},
options: [
{
tooltip: {
trigger: "axis"
},
grid: {
y: 30,
y2: 100,
},
xAxis: {
type: 'category',
data: xData
},
yAxis: {
type: 'value'
},
series: [{
type: "bar",
barWidth: 30,
color: '#298EF8'
}]
}
]
};
for (var j = 0; j < xData.length; j++) {
option.options.push({
series: [
{
data: yData
}
]
});
}
chart.setOption(option);
就可以看到 图1 这个结果:
BUT,柱状图和时间轴的刻度 “严重错位”,实在是看着难受,所以有强迫症的我决定改造改造。
首先,我们需要明白一个思路,想要让两个部分的刻度完全吻合,就必须保证两点:
1、保证柱状图的第一根柱子中心和时间轴的第一个刻度在同一个位置;
2、保证柱状图的最后一根柱子中心和时间轴的最后一个刻度在同一个位置。
简单来说,这不就是列两个等式,解这两个等式就可以了吗?!
设echarts容器的宽度为W,柱子个数为n,柱状图左边距为bl,右边距为br,时间轴左边距为tl,右边距为tr,最左端到第一个刻度的距离为x,最右端到最后一个刻度的距离为y(如图2)
根据上面的两个保证,我们就可以列出如下两个等式
bl+(W-bl-br)/n/2 = tl+x
br+(W-bl-br)/n/2 = tr+y
不要被两个等式中这么多未知数吓到,可以简单思考一下,这两个等式中,有哪些值是可以取到,哪些值其实是固定值。
很显然,W、n可以取到,x、y是固定值,这样就只剩下了未知数bl、br、tl、tr。只要我们随意设置两个固定值,那么就可以求出另两个未知数。
由于柱状图左侧或者右侧会有内容,所以我们这里固定bl、br,这样上面的等式就可以改写为:
tl = bl+(W-bl-br)/n/2 - x
tr = br+(W-bl-br)/n/2 - y
修改代码:
let xData = [];
let yData = [];
for (let key in data) {
xData.push(key);
yData.push(data[key]);
}
let chartEl = document.getElementById("timeline");
let chartElWidth = chartEl.offsetWidth;
let chart = echarts.init(chartEl);
let barLeft = 100; // 修改内容
let barRight = 80; // 修改内容
let timelineLeft = barLeft + ((chartElWidth - barLeft - barRight) / xData.length / 2) - 74; // 修改内容
let timelineRight = barRight + (chartElWidth - barLeft - barRight) / xData.length / 2 - 40; // 修改内容
let option = {
timeline: {
data: xData,
axisType: "category",
show: true,
autoPlay: true,
playInterval: 2000,
bottom: 20,
left: timelineLeft, // 修改内容
right: timelineRight, // 修改内容
symbol: "emptyCircle",
symbolSize: 5,
color: "#0088cc",
checkpointStyle: {
symbolSize: 8,
color: "#0088cc",
borderColor: "rgba(0,136,204,0.5)"
},
controlStyle: {
emphasis: {
color: "#176FCC",
borderColor: "#176FCC"
}
},
label: {
normal: {
show: true
}
}
},
options: [
{
tooltip: {
trigger: "axis"
},
grid: {
y: 30,
y2: 100,
left: barLeft, // 修改内容
right: barRight // 修改内容
},
xAxis: {
type: 'category',
data: xData
},
yAxis: {
type: 'value'
},
series: [{
type: "bar",
barWidth: 30,
color: '#298EF8'
}]
}
]
};
for (var j = 0; j < xData.length; j++) {
option.options.push({
series: [
{
data: yData
}
]
});
}
chart.setOption(option);
就会得到如下效果
PS:
实践中会发现,时间轴的最左端和最右端并不是肉眼可见的最左端和最右端,改造 图2 应该是如下 图4 这样