Chart.js에 데이터 값을 표시하는 방법


118

Chart.js를 사용할 수 있는지 묻고 싶습니다. 데이터 값을 표시하려면? 그래프를 인쇄하고 싶습니다.

조언을 해주셔서 감사합니다.


내 그래프가 완벽하게 작동합니다. .. 그냥 LineBar 차트에 데이터 값을 표시하고 싶습니다. 그런 다음 그래프를 인쇄 할 수 있습니다. 이제 마우스 이벤트만으로 데이터 값을 표시 할 수 있기 때문입니다
FuSsA

답변:


138

후기 편집 : Chart.js의 공식 플러그인 2.7.0+이 있습니다 : https://github.com/chartjs/chartjs-plugin-datalabels

원래 답변 :

AnimationComplete에서 점 / 막대를 반복하고 값을 표시 할 수 있습니다.


시사

여기에 이미지 설명 입력


HTML

<canvas id="myChart1" height="300" width="500"></canvas>
<canvas id="myChart2" height="300" width="500"></canvas>

스크립트

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
    datasets: [
        {
            fillColor: "#79D1CF",
            strokeColor: "#79D1CF",
            data: [60, 80, 81, 56, 55, 40]
        }
    ]
};

var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.points.forEach(function (points) {
                ctx.fillText(points.value, points.x, points.y - 10);
            });
        })
    }
});

var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.bars.forEach(function (bar) {
                ctx.fillText(bar.value, bar.x, bar.y - 5);
            });
        })
    }
});

바이올린-http: //jsfiddle.net/uh9vw0ao/


같은 차트에 두 개의 꺾은 선형 차트가 있으면 어떻게합니까?
FuSsA 2015

1
위의 경우에도 여전히 값이 표시되지만 포인트가 서로 너무 가까우면 겹침을 볼 수 있습니다. 그러나 항상 논리를 넣어 값 위치를 변경할 수 있습니다. 예를 들어 -jsfiddle.net/hh719qex ( 컬러 프린터가있는 경우). 2 개의 시리즈 만있는 경우 2 개의 포인트가 서로 2 개 가까이있는 경우 textBaseline을 다르게 설정하는 것과 같은 작업을 수행 할 수도 있습니다.
potatopeelings

4
v1.0.2의 경우 v2.1.3의 경우이 작업을 수행하는 방법은 무엇입니까? 객체 구조는 이후 버전에서 다릅니다.
techie_28

2
@potatopeelings onComplete여기서 콜백 을 사용 했지만 마우스 오버가 차트의 막대에 있으면 다시 그리기로 인해 숫자가 깜박일 때도 발생합니다 onAnimationComplete. 이 콜백을 기존 차트 코드와 함께 사용할 수 없습니다 (아래 var chartBar에서 pastebin.com/tT7yTkGh 참조 )
techie_28

1
그래프 막대 위에 도구 설명과 데이터가 모두 필요합니다. 도구 설명이 표시되면 막대 상단의 데이터가 투명 도구 설명에 보이는 흰색으로 바뀝니다. 이 문제를 어떻게 해결할 수 있습니까?
LJP

82

다음은 Chart.js 2.3의 업데이트 된 버전입니다.

2016 년 9 월 23 일 : 선 / 막대 유형 모두에 대해 v2.3에서 작동하도록 코드를 편집했습니다.

중요 : 애니메이션이 필요하지 않더라도 기간 옵션을 0으로 변경하지 마십시오. 그렇지 않으면 chartInstance.controller is undefined 오류가 발생합니다.

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
        datasets: [
            {
                fillColor: "#79D1CF",
                strokeColor: "#79D1CF",
                data: [60, 80, 81, 56, 55, 40]
            }
        ]
    };

var opt = {
    events: false,
    tooltips: {
        enabled: false
    },
    hover: {
        animationDuration: 0
    },
    animation: {
        duration: 1,
        onComplete: function () {
            var chartInstance = this.chart,
                ctx = chartInstance.ctx;
            ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
            ctx.textAlign = 'center';
            ctx.textBaseline = 'bottom';

            this.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.controller.getDatasetMeta(i);
                meta.data.forEach(function (bar, index) {
                    var data = dataset.data[index];                            
                    ctx.fillText(data, bar._model.x, bar._model.y - 5);
                });
            });
        }
    }
};
 var ctx = document.getElementById("Chart1"),
     myLineChart = new Chart(ctx, {
        type: 'bar',
        data: chartData,
        options: opt
     });
<canvas id="myChart1" height="300" width="500"></canvas>


막대 그래프에서이 작업을 시도 할 때 "Uncaught TypeError : Cannot read property '0'of undefined"가 발생합니다. 막대가 "dataset.metaData [i] ._ model"이외의 것을 사용합니까?
Chris Ensell

실제로는 var model = dataset._meta [i] .data [0] ._ model;
Flanamacca

그것은 또한 완전한 진실이 아닙니다. 여전히 예외가 있습니다. 그것을 알아 내려고 노력할 것입니다.
val

var model = dataset._meta [0] .data [i] ._ model; 사실은.
brian

2
_meta [0]만큼 간단하지 않은 것 같습니다. 사실 _meta 객체는 배열이 아니며 숫자를 키로하는 단일 요소가 있습니다. 숫자가 무엇인지에 대한 근거를 알 수 없으므로 다음과 같이 키 목록을보고 첫 번째 요소를 가져옵니다. var model = dataset._meta [Object.keys (dataset._meta) [0]] .data [i] ._ model;
IrishDubGuy

34

이 애니메이션 옵션은 막대 차트의 2.1.3에서 작동합니다.

약간 수정 @Ross 답변

animation: {
duration: 0,
onComplete: function () {
    // render the value of the chart above the bar
    var ctx = this.chart.ctx;
    ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
    ctx.fillStyle = this.chart.config.options.defaultFontColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    this.data.datasets.forEach(function (dataset) {
        for (var i = 0; i < dataset.data.length; i++) {
            var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
            ctx.fillText(dataset.data[i], model.x, model.y - 5);
        }
    });
}}

3
또한 세트로했다 hover: {animationDuration: 0}호버 멀리 애니메이션 레이블 중지
iamyojimbo

1
또한 범례에서 무언가를 숨길 때 레이블을 숨기려면 forEach 루프 앞에 다음을 추가해야합니다..filter(dataset => !dataset._meta[0].hidden)
iamyojimbo

1
이 방법을 사용하면 막대 위에 충분한 공간이없는 경우 값이 잘립니다.
의 Janne Annala

2
정말 못 생겼어요 ^^ 좋은 직업
La masse

보기에는 좋지만 툴팁을 다시 그릴 때 깜박입니다. 또한 결합 된 차트와 누적 막대의 누적 데이터 레이블에서 충돌을 처리하지 않습니다. 물론 더 많은 코딩이 필요합니다.
dma_k

22

chartJS v2.x에서이 작업을 수행하는 가장 좋은 옵션은 플러그인을 사용하는 것이므로 옵션에 큰 코드 블록이 없습니다. 또한 막대 위로 마우스를 가져갈 때 데이터가 사라지는 것을 방지합니다.

즉, 차트를 그린 후 텍스트를 추가하는 플러그인을 등록하는이 코드를 사용하면됩니다.

Chart.pluginService.register({
    afterDraw: function(chartInstance) {
        var ctx = chartInstance.chart.ctx;

        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        chartInstance.data.datasets.forEach(function (dataset) {
            for (var i = 0; i < dataset.data.length; i++) {
                var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
                ctx.fillText(dataset.data[i], model.x, model.y - 2);
            }
        });
  }
});

Chart.plugins.register ({
hasentopf 2016-08-26

나는을 사용해야했다 Chart.defaults.global.tooltips.enabled = false;. 이 솔루션의 문제는 afterDraw함수가 수백 번 호출되어 CPU 오버 헤드를 생성 한다는 것입니다. 그래도 지금은 눈 깜빡임없이 유일한 답입니다. horizontalBar차트에 대해 더 나은 렌더링이 필요한 경우 ctx.textAlign = 'left'; ctx.textBaseline = 'middle';ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev

훨씬 더 깨끗하고 모듈화 된 솔루션입니다.
hadaytullah

20

Chart.js 2.0 이상에 대한 @Ross의 답변에 따라 막대의 높이가 스케일 경계로 선택되는 경우를 방지하기 위해 약간의 조정을 포함해야했습니다.

예

animation막대 차트 옵션 의 속성 :

animation: {
            duration: 500,
            easing: "easeOutQuart",
            onComplete: function () {
                var ctx = this.chart.ctx;
                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset) {
                    for (var i = 0; i < dataset.data.length; i++) {
                        var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                            scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
                        ctx.fillStyle = '#444';
                        var y_pos = model.y - 5;
                        // Make sure data value does not get overflown and hidden
                        // when the bar's value is too close to max value of scale
                        // Note: The y value is reverse, it counts from top down
                        if ((scale_max - model.y) / scale_max >= 0.93)
                            y_pos = model.y + 20; 
                        ctx.fillText(dataset.data[i], model.x, y_pos);
                    }
                });               
            }
        }

차트 위에 마우스를 올리면 텍스트가 깜빡입니다 .. ctx.save()마지막에 전화 를 걸어
봤지만

onComplete나는이와 동일 blink.Would에 다시 그리기 및 텍스트가 나타납니다 원인이되는 바의에 공중 선회 할 때 호출 다시 실행 onAnimationComplete아니라? 내가 사용할 수 없습니다 나처럼 onAnimationComplete기존 코드를 호출 다시 (볼 var chartBar의 아래쪽에 페이스트 빈. com / tT7yTkGh
techie_28

파이 차트에서도 똑같이 할 수 있습니까
Ravi Khambhati 2017 년

@RaviKhambhati 예,이 답변에서 확인할 수 있습니다 : stackoverflow.com/a/38797604/6402571
Hung Tran

17

플러그인 chartjs-plugin-datalabels 를 사용하는 경우 다음 코드 옵션 객체가 도움이 될 것입니다.

import 'chartjs-plugin-datalabels';typescript 파일에서 가져 오거나 <script src="chartjs-plugin-datalabels.js"></script>javascript 파일에 참조를 추가 했는지 확인하십시오 .

options: {
    maintainAspectRatio: false,
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
        }
      }]
    },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'top',
        formatter: Math.round,
        font: {
          weight: 'bold'
        }
      }
    }
  }

1
당신의 대답은 너무 간단하고 저에게 효과적이었습니다. 감사합니다. 즐거운 코딩입니다.
Bandham Manikanta

7

좋은 대답 에 따라 막대 차트에 다음 옵션을 사용합니다.

var chartOptions = {
    animation: false,
    responsive : true,
    tooltipTemplate: "<%= value %>",
    tooltipFillColor: "rgba(0,0,0,0)",
    tooltipFontColor: "#444",
    tooltipEvents: [],
    tooltipCaretSize: 0,
    onAnimationComplete: function()
    {
        this.showTooltip(this.datasets[0].bars, true);
    }
};

window.myBar = new Chart(ctx1).Bar(chartData, chartOptions);

막대 차트

이것은 여전히 ​​툴팁 시스템과 그의 장점 (자동 위치 지정, 템플릿 등)을 사용하지만 장식 (배경색, 캐럿 등)은 숨 깁니다.


차트 유형에 따라 구현이 변경 될 수 있습니다. 예를 들어 꺾은 선형 차트 this.datasets[0].points의 경우 .bars. 이 솔루션은 툴팁 시스템을 사용하기 때문에 선호합니다.
Telmo Marques

1
이전 버전에 대한이 솔루션. 최신 버전 즉 2.1.3에서이를 달성하는 방법. 애니메이션 onComplete콜백 에서 potatopeelings & Huang Trang 답변을 사용 했지만 차트의 막대 위로 마우스를 가져가도 텍스트가 다시 그려지고 원치 않는 깜박임 효과가 발생하는 경우에도 트리거 afterDraw됩니다. potatopeelings에서 제공하는 바이올린에서는 발생하지 않습니다.
techie_28

6

chart.js 샘플에서 (Chart.js-2.4.0 / samples / data_labelling.html 파일) :

```// 데이터 레이블을 제공하는 플러그인 정의

    Chart.plugins.register({
        afterDatasetsDraw: function(chartInstance, easing) {
            // To only draw at the end of animation, check for easing === 1
            var ctx = chartInstance.chart.ctx;

            chartInstance.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.getDatasetMeta(i);
                if (!meta.hidden) {
                    meta.data.forEach(function(element, index) {
                        // Draw the text in black, with the specified font
                        ctx.fillStyle = 'rgb(0, 0, 0)';

                        var fontSize = 16;
                        var fontStyle = 'normal';
                        var fontFamily = 'Helvetica Neue';
                        ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);

                        // Just naively convert to string for now
                        var dataString = dataset.data[index].toString();

                        // Make sure alignment settings are correct
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'middle';

                        var padding = 5;
                        var position = element.tooltipPosition();
                        ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
                    });
                }
            });
        }
    });

```


if (chart.config.type == "horizontalBar")를 수행 한 다음 중앙 정렬을 위해 10의 사용자 지정 세로 패딩을 정의하여 가로 막대 차트에 정렬하기위한 선을 추가했습니다.
Jeff Beagley

6

이 플러그인을 사용하는 것이 좋습니다 : https://github.com/chartjs/chartjs-plugin-datalabels

플러그인을 js 파일로 가져 오기만하면 차트에 레이블을 추가 할 수 있습니다. 예 :

import 'chartjs-plugin-datalabels'

https://chartjs-plugin-datalabels.netlify.com/options.html 문서를 사용하여 미세 조정할 수 있습니다.


2
가장 쉬운 방법은 "코드"가 필요하지 않으며 표준 "옵션"개체를 사용하여 사용자 정의 할 수 있습니다. 헤드 업 : 최소 요구 charts.js 버전은 2.7.0 나는 CDN에서 2.5.0를 참조하고 차트 변경 ... 없었다,
GBU

@GBU 옵션 속성은 무엇입니까?.
Bhimbim

5

@ajhuddy의 답변을 조금 수정했습니다. 막대 차트에만 해당됩니다 . 내 버전은 다음을 추가합니다.

  • 값에 대한 애니메이션 페이드 인.
  • 막대가 너무 높으면 막대 내부에 값을 배치하여 클리핑을 방지합니다.
  • 깜박임이 없습니다.

예

단점 : 값이있는 막대 위로 마우스를 가져 가면 값이 약간 들쭉날쭉하게 보일 수 있습니다. 호버 효과를 비활성화하는 솔루션을 찾지 못했습니다. 자신의 설정에 따라 조정이 필요할 수도 있습니다.

구성 :

bar: {
  tooltips: {
    enabled: false
  },
  hover: {
    animationDuration: 0
  },
  animation: {
    onComplete: function() {
      this.chart.controller.draw();
      drawValue(this, 1);
    },
    onProgress: function(state) {
      var animation = state.animationObject;
      drawValue(this, animation.currentStep / animation.numSteps);
    }
  }
}

도우미 :

// Font color for values inside the bar
var insideFontColor = '255,255,255';
// Font color for values above the bar
var outsideFontColor = '0,0,0';
// How close to the top edge bar can be before the value is put inside it
var topThreshold = 20;

var modifyCtx = function(ctx) {
  ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  return ctx;
};

var fadeIn = function(ctx, obj, x, y, black, step) {
  var ctx = modifyCtx(ctx);
  var alpha = 0;
  ctx.fillStyle = black ? 'rgba(' + outsideFontColor + ',' + step + ')' : 'rgba(' + insideFontColor + ',' + step + ')';
  ctx.fillText(obj, x, y);
};

var drawValue = function(context, step) {
  var ctx = context.chart.ctx;

  context.data.datasets.forEach(function (dataset) {
    for (var i = 0; i < dataset.data.length; i++) {
      var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
      var textY = (model.y > topThreshold) ? model.y - 3 : model.y + 20;
      fadeIn(ctx, dataset.data[i], model.x, textY, model.y > topThreshold, step);
    }
  });
};

Janne, 해결책에 감사드립니다. 멋져 보입니다. 하지만 내 값이 실제로 약간 큰 (십진수 5 개) 화면 크기가 작거나 차트가 많을 때 숫자가 서로 겹쳐지는 상황이 있습니다. 반응 형으로이 작업을 수행 할 수있는 방법이 있습니까? 마치 막대 아래의 레이블처럼 공백이 없을 때 숫자가 회전하도록 만들까요?
Phiter

@PhiterFernandes modifyCtx 함수에서 현재 화면 크기를 확인하고 ctx.rotate를 사용하여 회전이 가능해야한다고 생각합니다. 그러나 회전시기를 결정하기 위해 값 크기를 사용 가능한 공간과 비교하는 방법을 모르겠습니다.
Janne Annala

modifyCtx 함수는 크기 조정이 아닌 한 번만 작동합니다. chart.js 소스 코드를 살펴보고 x 축에서 레이블이 회전하는 위치를 살펴 보겠습니다. 내가 뭔가를 본다면 내가 뭔가를 시도하고 여기서 말해 줄게, 알았지? =)
Phiter

버전 2.3.0, 라인 7075에서 뭔가를 찾았습니다. calculateTickRotation, 그것은 Scale 함수 안에 있습니다. 나는 그것을 분석 할 것이다.
Phiter

5

내 경험상 chartjs-plugin-datalabels 플러그인 을 포함하면 ( <script>페이지의 chart.js 태그 뒤에 태그 를 배치해야 함 ) 차트에 값이 표시되기 시작합니다.

그런 다음 선택하면 필요에 맞게 사용자 정의 할 수 있습니다. 사용자 정의는 여기에 명확하게 설명되어 있지만 기본적으로 형식은 다음과 같은 가상의 예와 같습니다.

var myBarChart = new Chart(ctx, {
    type: 'bar',
    data: yourDataObject,
    options: {
        // other options
        plugins: {
            datalabels: {
                anchor :'end',
                align :'top',
                // and if you need to format how the value is displayed...
                formatter: function(value, context) {
                    return GetValueFormatted(value);
                }
            }
        }
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.