HighChart 사용하기

lsj8367·2021년 4월 15일
0

Highchart

HighChart로 그래프를 구현

진행하는 프로젝트 중 하이차트를 구현하여 특정 조건들을 구현해야 해서 이번 기회에 사용하게 된 하이차트 이다. 필요한 기능 구현 외에 추가적으로 알면 좋겠어서 주석으로 어떠한 기능들을 하는지 메모를 해두었다.

setOptions로 기능을 구현하기

Highcharts.setOptions({
    chart: {
        backgroundColor: {
            linearGradient: [0, 0, 500, 500],
            stops: [
                [0, 'rgb(255, 255, 255)'],
                [1, 'rgb(240, 240, 255)']
            ]
        },
        borderWidth: 2,
        plotBackgroundColor: 'rgba(255, 255, 255, .9)',
        plotShadow: true,
        plotBorderWidth: 1
    }
});
const chart1 = new Highcharts.Chart({
    chart: {
        renderTo: 'container',
    },
    xAxis: {
        type: 'datetime'
    },
    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
        pointStart: Date.UTC(2010, 0, 1),
        pointInterval: 3600 * 1000 // one hour
    }]
});
const chart2 = new Highcharts.Chart({
    chart: {
        renderTo: 'container2',
        type: 'column'
    },
    xAxis: {
        type: 'datetime'
    },
    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
        pointStart: Date.UTC(2010, 0, 1),
        pointInterval: 3600 * 1000 // one hour
    }]
});

이렇게 setOptions를 주게되면 전체 그래프들에 대해 옵션값을 준다.

const options

아래는 const 상수에 options를 넣고 마지막에 이 options를 넣어 그래프를 구현하는 예제이다.

이 예제에서는 클릭해서 확대하는 옵션을 구현하는데 상당한 시간을 소요했었다. zoom 옵션이 존재하지만 그 기능은 특정 버튼이 전체적으로 확대 또는 축소를 진행하는 버튼이었고 highchart api 사이트에도 zoom이라고 검색해도 나오지 않아서 계속 찾던중 setExtremes로 구현을 해야 특정 부분을 확대해주는 기능이 되는것을 알게 되었다.

그러면서 동시에 줌을 원 상태로 복구시켜주는 reset 버튼을 따로 구현한다면, chart.zoomout()을 button의 addEventListener를 통해 구현을 하였겠지만, 차트위에 같이 표시해주는 것이 사용자의 입장에서 편리할 것 같았기 때문에 기본으로 제공해주는 showResetZoom으로 버튼을 생성해주었다.

입사해서 첫 프로젝트를 진행하는 만큼 코드의 품질은 썩 좋지 않지만 시간이 나면 리팩토링을 해야겠다는 생각이 든다.

let test1;
let test2;
let count1 = 0;
let cnt = 0;

const options = {
    chart: {
        type: 'scatter', //그래프의 유형
        renderTo: 'container2', // div의 id값
        // zoomType: 'xy', //드래그로 특정 점 구간 확대기능 x, y, xy
        // panning: true, //panning 줄건지
        // panKey: 'shift', //어떤키로 panning 이동하게 할건지 shift, alt, ctrl,
    },
    credits: { //highcharts.com 지우기
        enabled: false
    },

    title:{
        text: '제목',
    },

    subtitle: {
        text: '부제목',
    },

    // yAxis: { //y축 설정
    //     labels: {
    //         formatter: function() {
    //             return this.value; //y축 값에 + 어떤값을 추가할 수 있다.
    //         }
    //     },
    // },

    xAxis : {
        // categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        // crosshair: { //합친 점에 대한 선
        //     width: 10, //폭

        //     color: '#e6e6e6', //색
        //     dashStyle: 'Solid' //모양
        //     // 'Dash' | 'DashDot' | 'Dot' | 'LongDash' | 'LongDashDot' | 'LongDashDotDot' | 'ShortDash' | 'ShortDashDot' | 'ShortDashDotDot' | 'ShortDot' | 'Solid'
        // },
        // tickInterval: 2, //2칸 간격
     },

    yAxis: [
    	{ //--- Primary yAxis
        title: {
            text: 'Temperature'
        },
        labels: {
            format: '{value} %', //데이터의 표시 형식
        },

   		 },

    ],
    series: [ //data 여러개 넣으면 한번에 여러개의 그래프 도시가능
        {
            keys: ['y', 'id'], //키 id값 설정해줌.
            data: [
                [29.9, '0'], [71.5, '1'], [106.4, '2'], [129.2, '3'],
                [29.9, '4'], [71.5, '5'], [106.4, '6'], [129.2, '7'],
                [29.9, '8'], [71.5, '9'], [106.4, '10'], [129.2, '11'],
                [29.9, '12'], [71.5, '13'],
            ],

            
        },
            
        ],

    plotOptions: {
        series: {
            cursor: 'pointer', //점에 마우스를 가져다대면 포인터가 손모양으로 바뀜
            // allowPointSelect: true,
            marker: {
                states: {
                  hover: {
                    fillColor: 'red' //점에 마우스 올렸을때 색이 바뀜
                  }
                }
            },
            
            point: { //각각의 점에 대한 클릭 옵션
                events: {
                  click: function(e) {

                    if(count1 == 0){
                        this.color='red';
                        test1 = e.point.x;
                    }
                    count1++;

                    if(count1 == 2){
                        this.color='red';
                        test2 = e.point.x;
                        
                        chart.xAxis[0].setExtremes(test1, test2); //특정구간 클릭한 두점으로 x축 확대해줌.
                        chart.showResetZoom(); //리셋 줌버튼 생성
                        this.color='';
                        count1 = 0;
                    }
                }
              }
            },

            events: {
                click: function(e) {
                    cnt++;
                    if(cnt == 2){
                        this.update({
                            color: '' //기본 컬러들로 다시 되돌림
                        });
                        cnt = 0;
                    }
                }
            },
        }
    },

    // tooltip: {
    //     enabled: false //기본 차트 정보 나오는것 제거
    // },

    annotations: [{
            labels: [{
                point: '0', //n번째 점
                //format: '{y:.2f} mm' //format 형식
                x: 50, //선 길이 왼쪽오른쪽 조절
                y: 200, // 위아래 선길이

                //format: '{y:.f} %', //format 형식
                format: '비가 많이왔음',
            },
                // }, {
                //     point: '1',
                //     // text: '{point.plotY:.2f} px' 표시형식
                // }, {
                //     point: '2'
                // }, {
                //     point: '3'
                // },
            ],

            events: {
                click: function() {
                    window.open('library/test.html', 'windowPop', 'width=400, height=600, left=500, top=200, resizable = yes')
                }
            }
            // labelOptions: {
            //     formatter: function () {
            //         return this.series.data;
            //     }
            // }
    }],
}

const chart = new Highcharts.Chart(options);

function downloadPNG(){ //이미지로 저장
	chart.exportChart({
        filename: '123', //파일명
        type:"image/png" //파일 저장 타입
    });
}

const 배열에 아이템을 삽입하는건 가능하다. 하지만 재할당은 불가능하다.

 options.series.push({ 
     name: 'John',
     data: [3, 4, 2],
 })

이렇게 배열을 push를 사용하여 넣어줄 수 있다.

Json으로 배열에 넣어 그래프 구현

아래는 dict type으로 각각의 데이터를 삽입하고 구간으로 묶어서 집합하여 시각화해주는 예제이다.

var json = [
    {
        "timestamp": "2018-05-30 00:33:05",
        "temperature": "27.39",
        "humidity": "66.57",
        "pressure": "99.21",
        "mib" : "1.1",
        "zeros" : '0',
    },
    {
        "timestamp": "2018-06-15 00:35:05",
        "temperature": "33.21",
        "humidity": "69.57",
        "pressure": "89.00",
        "mib" : "1.1",
        "zeros" : '0',
    },
    {
        "timestamp": "2018-06-30 00:35:05",
        "temperature": "33.21",
        "humidity": "69.57",
        "pressure": "89.00",
        "mib" : "1.1",
        "zeros" : '0',
    },
    {
        "timestamp": "2018-07-30 00:37:05",
        "temperature": "25.39",
        "humidity": "69.57",
        "pressure": "95.00",
        "mib" : "1.1",
        "zeros" : '0',
    },
    {
        "timestamp": "2018-08-30 00:38:05",
        "temperature": "22.39",
        "humidity": "64.57",
        "pressure": "95.88",
        "mib" : "1.1",
        "zeros" : '0',
    },
    {
        "timestamp": "2018-09-30 00:41:05",
        "temperature": "38.39",
        "humidity": "50.57",
        "pressure": "95.00",
        "mib" : "1.1",
        "zeros" : '0',
    },
    ];

$(function () {
    //각각의 시리즈별 데이터 배열
    const temperature = [],
        humidity = [],
        pressure = [],
        mib = [],
        zeros = [];
    
        //시리즈별로 for루프 진행해서 배열에 넣어줌.
    $.each(json, function (i, el) {
        const tmpTimestamp = new Date(el.timestamp).getTime() //밀리초까지 해서 스탬프에 담음

        temperature.push({
            x: tmpTimestamp,
            y: parseFloat(el.temperature)
        })
        humidity.push({
            x: tmpTimestamp,
            y: parseFloat(el.humidity)
        })
        pressure.push({
            x: tmpTimestamp,
            y: parseFloat(el.pressure)
        })
        mib.push({
            x:tmpTimestamp,
            y: parseFloat(el.mib)
        })
        zeros.push({
            x: tmpTimestamp,
            y: parseFloat(el.zeros)
        })
    })
    //이름과 데이터값 y축 설정과 매칭시킴
    const series = [ //점의 정보 출력하는 곳
        {
            name: '2-MIB',
            data: mib,
            yAxis: '0',
        },
        
        {
            name: '온도', //그래프 점의 정보
            data: temperature,
            yAxis: '1',
        },
        {
            name: '습도',
            data: humidity,
            yAxis: '2',
        },
        {
            name: '압력',
            data: pressure,
            yAxis: '3',
        },
        {
            name: '기준점',
            data: zeros,
            yAxis: '4',
        }

    ]

    $('#container').highcharts({
        series: series,
        chart:{
            type: 'spline', //차트 옵션
            zoomType: 'x', //드래그로 특정 점 구간 확대기능 x, y, xy
            // panning: true, //panning 줄건지
            // panKey: 'shift', //어떤키로 panning 이동하게 할건지 shift, alt, ctrl, 
        },
        credits: { //highcharts.com 지우기
            enabled: false
        },
        
        xAxis: {
            type: 'datetime',  //유형 "linear" | "logarithmic" | "datetime" | "category" | "treegrid"
            // minPadding: 0.1,
            // maxPadding: 0.1,
            labels: {
                rotation: -45, //x라벨 기울이기 45도
                format: '{value:%Y-%m-%d}', //날짜형식 포맷
            },

            crosshair: { //합친 점에 대한 선
                width: 10, //폭

                color: '#e6e6e6', //색
                dashStyle: 'Solid' //모양
                // 'Dash' | 'DashDot' | 'Dot' | 'LongDash' | 'LongDashDot' | 'LongDashDotDot' | 'ShortDash' | 'ShortDashDot' | 'ShortDashDotDot' | 'ShortDot' | 'Solid'
            },
            
        },

        //각 시리즈별로 매칭 y축
        yAxis: [
            {
                id: '0',
                title: {
                    text: '2-mib',
                },
            },

            {
                id: '1',
                opposite: true, //이 기능이 오른쪽에 붙여주게 하는것 기본값은 false
                title: {
                    text: '온도',
                },
                labels: {
                    format: '{value}°C',
                }
            },

            {
                id: '2',
                opposite: true,
                title: {
                    text: '습도',
                },
                labels: {
                    format: '{value}%',
                    // style: { 컬러옵션주기
                    //     color: Highcharts.getOptions().colors[1] 
                    //   },
                }
            },

            {
                id: '3',
                opposite: true,
                title: {
                    text: '압력',
                },
                labels: {
                    format: '{value}mb',
                }
            },
            {
                id: '4',
                title: {
                    text: '기준점',
                },
            },
        ],

        title: {
            text: '그래프 여러개 그려서 컬럼 합치기'
        },

        tooltip: {
            shared: true, // 한 로우에 여러 컬럼의 값을 표시
        },

        plotOptions:{
            series:{
                marker: {
                    enabled: false, //해당 구간의 점 지우기
                }
            }
        },
    })
})

html에서의 코드 사용은 아래와 같다.

<!DOCTYPE html>
<html lang="ko">
    <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/modules/annotations.js"></script>
    <script src="https://code.highcharts.com/modules/exporting.js"></script>
    <meta charset="UTF-8">
    <title>하이차트 예제</title>
</head>

<body>
    <div id="container" style="width:100%; height:400px;"></div>
    <div id="container2" style="width:100%; height:400px;"></div>
    <button onclick="downloadPNG()">
        Download PNG
    </button>
</body>
    <script src="chart.js"></script>
</html>

글을 바빠서 작성하지 못하고 일주일만에 글을 쓴다. 공부할 때 조금만 시간을 더 잘 사용해서
글을 자주 쓰려고 노력해야 할 것 같다.

출처 : HighCharts API

profile
기록을 많이 하자!💻

0개의 댓글