관리 메뉴

Life goes slowly...

amCharts 4 라이브러리 pieChart 본문

프로그래밍/React.js

amCharts 4 라이브러리 pieChart

빨강소 2025. 7. 10. 23:40
728x90
반응형

 

 

먼저, amCharts 4 라이브러리가 설치되어 있는지 확인해주세요

 

npm install @amcharts/amcharts4

npm install @amcharts/amcharts4/charts

npm install @amcharts/amcharts4/themes

 

import React, { useLayoutEffect, useRef } from 'react';
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

// amCharts 폰트 또는 다른 글로벌 설정이 필요할 수 있습니다.
// am4core.options.autoSetClassName = true; // 클래스 이름 자동 설정 (선택 사항)

function Am4PieChart({ data }) {
  const chartRef = useRef(null);

  const effectiveData = data || [
    { value: 60, category: "Pass", count: 5 },
    { value: 40.0, category: "Fail", count: 9 },
  ];

  useLayoutEffect(() => {
    // 테마 등록 (항상 차트 생성 전에 등록)
    am4core.useTheme(am4themes_animated);

    // 1. 차트 인스턴스 생성
    // "am4chartdiv"는 차트를 렌더링할 HTML div 요소의 ID입니다.
    let chart = am4core.create("am4chartdiv", am4charts.PieChart);
    chartRef.current = chart; // 차트 인스턴스 저장

    // 2. 데이터 설정
    chart.data = effectiveData;

    // 3. 파이 시리즈 생성
    let pieSeries = chart.series.push(new am4charts.PieSeries());
    pieSeries.dataFields.value = "value";
    pieSeries.dataFields.category = "category";

    // 라벨 설정
    pieSeries.labels.template.adapter.add("text", function(text, target) {
      // {category}: {value.percent.formatNumber('#.#')}%, {count}ea 형식
      let dataItem = target.dataItem;
      let category = dataItem.category;
      let percentage = am4core.number.format(dataItem.value / chart.data.reduce((sum, item) => sum + item.value, 0) * 100, "#.#");
      let count = dataItem.dataContext.count;
      return `${category}: ${percentage}%, ${count}ea`;
    });

    // 라벨 위치 및 스타일 설정
    pieSeries.labels.template.radius = -40; // 슬라이스 중앙에서 안쪽으로 위치 조정
    pieSeries.labels.template.fill = am4core.color("#FFFFFF"); // 흰색 텍스트
    pieSeries.labels.template.strokeOpacity = 0; // 라벨 테두리 제거 (기본값일 수 있음)
    pieSeries.labels.template.horizontalCenter = "middle";
    pieSeries.labels.template.verticalCenter = "middle";
    pieSeries.labels.template.rotation = 0; // 라벨 텍스트 회전 비활성화

    // 라벨 배경 (사각형 형태)
    pieSeries.labels.template.background = new am4core.Rectangle();
    pieSeries.labels.template.background.fill = am4core.color("#000000"); // 검정색 배경
    pieSeries.labels.template.background.fillOpacity = 0.3; // 투명도
    pieSeries.labels.template.background.cornerRadius(3, 3, 3, 3); // 둥근 모서리
    pieSeries.labels.template.background.padding(4, 8, 4, 8); // 패딩

    // 라벨 선 제거 (amCharts 4에서는 `ticks`를 제어)
    pieSeries.ticks.template.disabled = true; // 틱(라인) 비활성화
    pieSeries.alignLabels = false; // 라벨이 슬라이스 내부에 정렬되도록 (겹칠 수 있음)

    // 슬라이스 설정
    pieSeries.slices.template.stroke = am4core.color("#fff"); // 슬라이스 테두리
    pieSeries.slices.template.strokeWidth = 1;
    pieSeries.slices.template.strokeOpacity = 1;

    // 호버 효과 비활성화 (툴팁 제거 및 상태 변경 비활성화)
    pieSeries.slices.template.tooltipText = ""; // 툴팁 텍스트를 비워 툴팁이 나타나지 않게 함
    pieSeries.slices.template.states.getKey("hover").properties.scale = 1; // 호버 시 확대 비활성화
    pieSeries.slices.template.states.getKey("active").properties.shiftRadius = 0; // 클릭 시 벗어나는 효과 비활성화

    // 슬라이스 색상 설정 (Pass/Fail에 따라 다르게)
    pieSeries.colors.list = [
      am4core.color("#67B7DC"), // Pass 색상 (첫 번째 데이터 아이템)
      am4core.color("#FF6347")  // Fail 색상 (두 번째 데이터 아이템)
      // 데이터가 더 많다면 다른 색상을 추가하거나 adapter를 사용할 수 있습니다.
    ];
    // 또는 adapter를 사용하여 동적으로 색상 지정 (더 유연함)
    // pieSeries.slices.template.adapter.add("fill", function(fill, target) {
    //   if (target.dataItem.category === "Pass") {
    //     return am4core.color("#67B7DC");
    //   } else if (target.dataItem.category === "Fail") {
    //     return am4core.color("#FF6347");
    //   }
    //   return fill;
    // });


    // 4. 레전드 (범례) 추가 (선택 사항)
    chart.legend = new am4charts.Legend();
    chart.legend.position = "bottom";

    // cleanup 함수
    return () => {
      if (chartRef.current) {
        chartRef.current.dispose();
      }
    };
  }, [effectiveData]);

  return (
    <div id="am4chartdiv" style={{ width: "100%", height: "500px" }}></div>
  );
}

export default Am4PieChart;
728x90
반응형
Comments