언급하지 않는 디테일한 echarts의 기능과 옵션은 공식 홈페이지를 참고 해주십시오.
부족한 부분이 많습니다. type사용이나 옵션생성에서 참고용으로 사용 해주시면 감사하겠습니다.
제 코드에서 가져왔기에 굵은 폰트 부분을 중점적으로 봐주십시오.

React와 Typescript를 사용.
Bump Chart란 마우스 호버시 해당하는 label의 그래프만 강조해서 보여주는 그래프이다.
useRef를이용해 Echart컴포넌트를 만들어 echarts.init 을 수행할 수 있는 dom엘리먼트에 접근한다.
npm install echarts
import React, { useEffect, useRef } from 'react';
import * as echarts from 'echarts';
type EchartProps = {
chartCss: React.CSSProperties;
chartOption: echarts.EChartsOption;
};
export default function Echart({ chartCss, chartOption }: EchartProps) {
const chartRef = useRef(null);
useEffect(() => {
const chartInstance = echarts.init(chartRef.current); // ECharts 초기화 및 인스턴스 생성하기
chartInstance.setOption(chartOption); // 차트 옵션 설정하기
const resizeHandler = () => {
chartInstance.resize(); // 차트 크기 조절
};
window.addEventListener('resize', resizeHandler);
return () => {
chartInstance.dispose();
window.removeEventListener('resize', resizeHandler); // resize 이벤트 리스너 제거하기
};
}, [chartOption]);
return <div ref={chartRef} style={chartCss} />;
}
export default function RankGraph({ teamRankData }: RankGraphProps) {
const { leagueId } = useLeagueInfo({ season: '2024' });
const { isPending, data: teamList, error } = useGetTeamList({ years: '2024', leagueId });
**const chartCss: React.CSSProperties = {
width: '100%',
height: '100vh',
};**
if (isPending) {
return <LoadingSpinner />;
}
if (error) {
return <div>error</div>;
}
**const option = generateRankGraph(teamRankData, teamList);**
**return <Echart chartCss={chartCss} chartOption={option} />;**
generateRankGraph 는 echarts의 옵션을 생성하는 함수입니다.constructor(teamRankData: TTeamRankInfo) {
this.teamRankData = teamRankData;
this.matchDayList = this.generateMatchDayList();
this.rankingData = this.generateRankingData();
}
public generateOption(teamList: TTeamList): EChartsOption {
return {
title: { text: '팀 순위 그래프' }, // 그래프 타이틀
tooltip: {
// 호버시 띄울 tooltip
trigger: 'item',
formatter: function (params) {
if (Array.isArray(params)) return ``;
return makeTooltipHTMLWithLogo(
params.seriesName as string,
params.name,
params.value as string | number,
teamList,
);
},
},
grid: {
left: 30,
right: 200,
bottom: 30,
containLabel: true,
},
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
// x축 데이터 생성
type: 'category',
splitLine: { show: true },
axisLabel: {
margin: 30,
fontSize: 16,
},
boundaryGap: false,
data: this.addedWeekMatchDayList,
},
yAxis: {
type: 'value',
axisLabel: {
margin: 30,
fontSize: 16,
formatter: '{value}위',
},
inverse: true,
interval: 1,
min: 1,
// max: Object.keys(this.rankingData).length,
max: 10,
},
series: this.generateSeriesList(teamList),
};
}
private generateSeriesList(teamList: TTeamList): SeriesOption[] {
const rich = this.makeRich(teamList);
return Object.entries(this.rankingData).map(([name, data]) => ({
name,
symbolSize: 15,
type: 'line',
smooth: true,
emphasis: { focus: 'series' },
endLabel: {
show: true,
formatter: (params) => {
const teamName = params.seriesName?.replace(reg, '');
return `{${teamName}|} ${params.seriesName}`;
},
distance: 20,
rich,
},
lineStyle: { width: 4 },
data,
}));
}
private generateRankingData(): Record<string, number[]> {
const rankingData: Record<string, number[]> = {};
this.matchDayList.forEach((matchDay, index) => {
this.teamRankData.rankInfo[matchDay - 1].ranks.forEach((rank) => {
if (!rankingData[rank.teamName]) {
rankingData[rank.teamName] = [];
}
rankingData[rank.teamName][index] = rank.rank;
});
});
return rankingData;
}
private generateMatchDayList(): number[] {
const allMatchDays = this.teamRankData.rankInfo.map((info) => info.matchDay);
const week = 5; // 보여줄 x갯수 = 5개 주
// 최근 5주차 순위 그래프
const start = Math.max(1, allMatchDays[allMatchDays.length - 1] + 1 - week);
return allMatchDays.slice(start - 1);
}