본문 바로가기
Front-end/React

[대시보드] amcharts 라이브러리 사용 리액트 Bar 차트

by 꼬바리 2023. 8. 27.

amcharts 로 차트를 생성하는 코드이다.

amcharts  중 버전 5 사용

amcharts 를 install 하고 import 해준다.

import * as am5 from "@amcharts/amcharts5";
import * as am5xy from "@amcharts/amcharts5/xy";
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";

 

데이터 구조

let data = {
	{category : '기억' , value : 1 } ,
    {category : '니은' , value : 1 } ,
    {category : '디귿' , value : 1 } ,
    ....
    ....
    {category : '히읏' , value : 1 } ,
}

 

 

다소 복잡해보이지만 여러 커스텀 가능함

Script Code

useEffect(() => {
        if(data){
            // Create root 
            const root = am5.Root.new(chartID);

            root.setThemes([am5themes_Animated.new(root)]);


            // Create chart
            const chart = root.container.children.push(
            am5xy.XYChart.new(root, {
                panX: false,
                panY: false,
                wheelX: "none",
                wheelY: "none"
            })
            );


            // Create axes
            const yRenderer = am5xy.AxisRendererY.new(root, { 
                minGridDistance: 30 
            });
            yRenderer.grid.template.set("location", 1);

            const yAxis = chart.yAxes.push(
                am5xy.CategoryAxis.new(root, {
                    maxDeviation: 0,
                    categoryField: "category",
                    renderer: yRenderer,
                })
            );

            // 라벨 두줄 세팅
            yAxis.get("renderer").labels.template.setAll({
                oversizedBehavior: "wrap",
                maxWidth: 200,
                textAlign : 'right'
            });

            const xAxis = chart.xAxes.push(
                am5xy.ValueAxis.new(root, {
                        maxDeviation: 0,
                        min: 0,
                        renderer: am5xy.AxisRendererX.new(root, {
                            visible: true,
                            strokeOpacity: 0.1,
                    }),
                })
            );


            // Create series
            const series = chart.series.push(
            am5xy.ColumnSeries.new(root, {
                name: "Series 1",
                xAxis: xAxis,
                yAxis: yAxis,
                valueXField: "value",
                sequencedInterpolation: true,
                categoryYField: "category"
            })
            );

            const columnTemplate = series.columns.template;

            columnTemplate.setAll({
                draggable: true,
                cursorOverStyle: "pointer",
                tooltipText: "drag to rearrange",
                cornerRadiusBR: 10,
                cornerRadiusTR: 10,
                strokeOpacity: 0
            });

            columnTemplate.adapters.add("fill", (fill, target) => {
                return chart.get("colors").getIndex(series.columns.indexOf(target));
            });

            columnTemplate.adapters.add("stroke", (stroke, target) => {
                return chart.get("colors").getIndex(series.columns.indexOf(target));
            });

            columnTemplate.events.on("dragstop", () => {
                sortCategoryAxis();
            });

            // Get series item by category
            function getSeriesItem(category) {
                for (var i = 0; i < series.dataItems.length; i++) {
                    var dataItem = series.dataItems[i];
                    if (dataItem.get("categoryY") == category) {
                    return dataItem;
                    }
                }
            }


            // Axis sorting
            function sortCategoryAxis() {
                // Sort by value
                series.dataItems.sort(function(x, y) {
                    return y.get("graphics").y() - x.get("graphics").y();
                });

                const easing = am5.ease.out(am5.ease.cubic);

                // Go through each axis item
                am5.array.each(yAxis.dataItems, function(dataItem) {
                    // get corresponding series item
                    const seriesDataItem = getSeriesItem(dataItem.get("category"));

                    if (seriesDataItem) {
                    // get index of series data item
                    const index = series.dataItems.indexOf(seriesDataItem);

                    const column = seriesDataItem.get("graphics");

                    // position after sorting
                    const fy =
                        yRenderer.positionToCoordinate(yAxis.indexToPosition(index)) -
                        column.height() / 2;

                    // set index to be the same as series data item index
                    if (index != dataItem.get("index")) {
                        dataItem.set("index", index);

                        // current position
                        const x = column.x();
                        const y = column.y();

                        column.set("dy", -(fy - y));
                        column.set("dx", x);

                        column.animate({ key: "dy", to: 0, duration: 600, easing: easing });
                        column.animate({ key: "dx", to: 0, duration: 600, easing: easing });
                    } else {
                        column.animate({ key: "y", to: fy, duration: 600, easing: easing });
                        column.animate({ key: "x", to: 0, duration: 600, easing: easing });
                    }
                    }
                });

                // Sort axis items by index.
                // This changes the order instantly, but as dx and dy is set and animated,
                // they keep in the same places and then animate to true positions.
                yAxis.dataItems.sort(function(x, y) {
                    return x.get("index") - y.get("index");
                });
            }

            yAxis.data.setAll(data);
            series.data.setAll(data);


            // Make stuff animate on load
            series.appear(1000);
            chart.appear(1000, 100);
        }
      }, [data]);

 

HTML 코드

<div id={chartID} className='watermark' style={{width : '100%' , height : '300px'}}>
</div>

바 차트에서 드래그 기능이 추가되어있다.

드래그하여 순서를 변경 가능

또한 레전드의 데이터길이 가 길때 자동 줄바꿈하게 옵션 설정 해주었다.

 

 

728x90
반응형

댓글