拖拽前:
拖拽后:
试过三种方案:
一、用echart的grapic进行定位竖线和文字,在dataZoom存在的时候没有动态效果
二、采用多个X轴
三、采用echarts的 custom 自定义画线和文字
推荐custom模式(getXAxisParentSeries函数已封装好)
let data = [
{ date: '2023-01', year: '2023', data: 2 },
{ date: '2023-02', year: '2023', data: 3 },
{ date: '2023-03', year: '2023', data: 4 },
{ date: '2023-04', year: '2023', data: 5 },
{ date: '2023-05', year: '2023', data: 3 },
{ date: '2023-07', year: '2023', data: 2 },
{ date: '2023-08', year: '2023', data: 4 },
{ date: '2023-09', year: '2023', data: 4 },
{ date: '2023-10', year: '2023', data: 6 },
{ date: '2023-11', year: '2023', data: 3 },
{ date: '2023-12', year: '2023', data: 4 },
{ date: '2024-01', year: '2024', data: 3 },
{ date: '2024-02', year: '2024', data: 2 },
{ date: '2024-03', year: '2024', data: 5 },
{ date: '2024-04', year: '2024', data: 5 },
{ date: '2024-05', year: '2024', data: 5 },
{ date: '2024-06', year: '2024', data: 6 },
]
let yearSeries = getXAxisParentSeries(data, 'year')
let opt = {
//其他设置
...
}
opt.series.push(yearSeries)
this.Chart.setOption(opt, { replaceMerge: ['series'] })
封装的工具函数
/**
* @description: 返回custom类型的series对象
* { object[] } xData 上方data数组
* { string } 数组中父级的key
* { lineHeight, lineStyle, textHeight, textStyle } 函数内画线和字体的样式
**/
export function getXAxisParentSeries(
xData,
key,
{ lineHeight, lineStyle, textHeight, textStyle } = { lineHeight: 160, lineStyle: {}, textHeight: 140, textStyle: {} }
) {
const x2StartArr = countXAxisStartIndex(xData, key)
const x2EndArr = countXAxisEndIndex(xData, key)
return {
type: 'custom',
data: xData.map(item => ''),
xAxisIndex: 0,
z: 9,
renderItem: (params, api) => {
let idx = params.dataIndex
let pointStart = api.coord([idx, 0])
let point2 = api.coord([idx + 1, 0])
let gap = (point2[0] - pointStart[0]) / 2
let start = x2StartArr.find(item => item.value === idx)
let end = x2EndArr.find(item => item.value === idx)
let group = {
id: `group_${key}_${idx}`,
type: 'group',
ignore: false,
x: pointStart[0] - gap,
y: pointStart[1],
children: [],
}
// 所有左侧竖线
if (start) {
group.children.push({
id: `line_${key}_${idx}`,
type: 'line',
shape: {
x1: 0,
y1: 0,
x2: 0,
y2: lineHeight || 160,
},
style: {
lineWidth: 1,
lineDash: 'solid',
stroke: 'rgba(0, 0, 0, 0.35)',
...lineStyle,
},
})
}
if (start || end) {
if (!end) {
let arrIdx = x2StartArr.findIndex(item => item.name === start.name && item.value === start.value)
end = x2EndArr[arrIdx]
}
if (!start) {
let arrIdx = x2EndArr.findIndex(item => item.name === end.name && item.value === end.value)
start = x2StartArr[arrIdx]
}
let pointStart = api.coord([start.value, 0])
let pointEnd = api.coord([end.value, 0])
let dataZoomStart = params.dataIndex - params.dataIndexInside
let pointZoomStart = api.coord([dataZoomStart, 0])
let dataZoomEnd = params.dataInsideLength - 1 - params.dataIndexInside + params.dataIndex
let pointZoomEnd = api.coord([dataZoomEnd, 0])
let name = start.name
let middle = (pointEnd[0] - pointStart[0]) / 2 + pointStart[0]
// 预防 start undefined情况
group.x = pointStart[0] - gap
// 间距太窄,文字竖向展示
if (end.value - start.value < 1) {
name = name.split('').join('\n')
}
if (middle <= pointZoomEnd[0] && middle >= pointZoomStart[0]) {
group.children.push({
id: `text_${key}_${idx}`,
type: 'text',
x: (pointEnd[0] - pointStart[0]) / 2 + gap,
y: textHeight || 140,
style: {
text: name,
textAlign: 'center',
fill: '#333',
...textStyle,
},
})
}
// 最右侧竖线
if (idx === xData.length - 1) {
group.children.push({
id: `line_${key}_${idx}`,
type: 'line',
shape: {
x1: pointEnd[0] - pointStart[0] + 2 * gap,
y1: 0,
x2: pointEnd[0] - pointStart[0] + 2 * gap,
y2: lineHeight || 160,
},
style: {
lineWidth: 1,
lineDash: 'solid',
stroke: 'rgba(0, 0, 0, 0.35)',
...lineStyle,
},
})
}
}
if (!group.children.length) {
group.ignore = true
}
return group
},
}
}
/**
* @description: 计算第N层X轴重复字符串终止索引 n>1
* @param { string[] } list 第n层x轴全部数据
* @return [{name: 2023, value:0, name: 2024, value: 12 }]
*/
export function countXAxisEndIndex(list, key) {
const temp = []
if (list.length) {
let name = list[0][key]
temp[0] = { name, value: 0 }
for (let i = 1; i < list.length; i++) {
if (name != list[i][key]) {
name = list[i][key]
temp.push({ name, value: i - 1 })
}
temp[temp.length - 1].value++
}
}
let name = list[list.length - 1][key]
if (name == temp[temp.length - 1].name) {
temp[temp.length - 1].value = list.length - 1
} else {
temp.push({ name, value: list.length - 1 })
}
return temp
}
/**
* @description: 计算第N层X轴重复字符串起始索引 n>1
* @param { string[] } list 第n层x轴全部数据
* @return [{name: 2023, value:11, name: 2024, value: 17 }]
*/
export function countXAxisStartIndex(list, key) {
const temp = []
if (list.length) {
let name = list[0][key]
temp[0] = { name, value: 0 }
for (let i = 1; i < list.length; i++) {
if (name != list[i][key]) {
name = list[i][key]
temp.push({ name, value: i })
}
}
}
return temp
}