[React + Typescript] Apache Echarts의 Bump Chart(Ranking) label과 tooltip에 이미지(image) 추가하기

SangHyun Park·2024년 10월 4일
0

React

목록 보기
3/3

요약

그래프 호버시 생성되는 tooltip과 맨오른쪽 label에 로고와 함께 출력하려고 한다.

option 생성의 tooltip옵션 formatter를 이용해 이미지가 추가된 html템플릿을 출력한다.

SeriesOption 의 rich속성을 통해 label에 이미지를 추가한다.

호버시 생성되는 tooltip

코드

EChartsOption 의 tooltip.formatter를 통해 string(html 템플릿을 반환한다.

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,
          );
        },
      },
      ...
    };
  }
  • item 하나당 하나의 데이터만 출력하므로 params가 배열이 아님을 보장하고 프로퍼티 자동완성을 위해 params가 배열이면 빈값을 출력
  • makeTooltipHTMLWithLogo 함수를 통해 html 템플릿을 반환
function makeTooltipHTMLWithLogo(
  seriesName: string, // 팀이름
  name: string, // 주차
  value: string | number, // 순위
  teamList: TTeamList,
): string {
  const teamLogo = teamList.find((team) => team.leagueTeamName === seriesName)?.logo;
  return `
          <div style="display: flex">
          ${teamLogo ? `<img style="width:24px; height:24px; margin-right: 4px" src=${teamLogo} alt=${teamLogo}/>` : null} <span>${seriesName}</span>
          </div>
          <div style="display: flex; justify-content: space-between;">
            <span>${name}</span>
            <span style="font-weight: bold">${value}위</span>
          </div>`;
}
  • 클래스 생성시 전달받은 teamList에서 생성하고자하는 team의 로고를 가져와 html 템플릿으로 생성해 반환

오른쪽 label(= endLabel)

코드

  • endLabel은 tooltip과 달리 string값만 출력할 수 있기에 formatter에서 html 템플릿을 반환할 수 없다.
  • rich 속성에서 image를 설정하고 formatter에 string template을 통해 이미지를 띄울 수 있다.

seriesOption

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,
    }));
  }
  • makeRich를 통해 생성한 rich의 속성과 같은 teamName 의 string 템플릿을 만들어 출력한다.

makeRich

private makeRich(teamList: TTeamList) {
    const rich: {
      [key: number | string]: {
        backgroundColor: {
          image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | string;
        };
        height: number;
      };
    } = {};
    Object.entries(this.rankingData).forEach(([name]) => {
      const teamName = name.replace(reg, '');
      const teamLogo = teamList.find((team) => team.leagueTeamName === name)?.logo;
      rich[teamName] = {
        backgroundColor: {
          image: teamLogo || '',
        },
        height: 20,
      };
    });

    return rich;
  }
  • 팀 이름과 로고 src가 있는 teamList를 순회하여 특수문자, 공백을 없애고 rich 객체에 속성과 값을 넣는다.

formatter 동작 방식

formatter: (params) => {
          const teamName = params.seriesName?.replace(reg, '');
          return `{${teamName}|} ${params.seriesName}`;
        },
  • formatter의 {teamName|}는 rich의 teamName에 설정된 image를 출력한다.

참고자료

https://echarts.apache.org/en/option.html#series-line.endLabel.formatter

https://echarts.apache.org/en/option.html#tooltip

profile
마라토너

0개의 댓글