як відобразити значення даних на Chart.js


118

Я хотів би запитати, чи можливо це за допомогою Chart.js для відображення значень даних? Я хочу надрукувати графік.

Дякую за будь-яку пораду.


мій графік працює ідеально .. я просто хочу відобразити значення даних у моїй діаграмі LineBar .. тоді я можу надрукувати свої графіки .. тому що тепер я можу відображати значення даних лише подіями миші
FuSsA

Відповіді:


138

Пізнє редагування: є офіційний плагін для Chart.js 2.7.0+для цього: https://github.com/chartjs/chartjs-plugin-datalabels

Оригінальна відповідь:

Ви можете провести цикл через точки / смуги onAnimationComplete та відобразити значення


Попередній перегляд

введіть тут опис зображення


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);
            });
        })
    }
});

Fiddle - http://jsfiddle.net/uh9vw0ao/


Що робити, якщо у мене в одній діаграмі були дві лінійні діаграми?
FuSsA

1
З вищезазначеним він усе ще відображатиме значення, але ви можете побачити перекриття, якщо точки занадто близькі один до одного. Але завжди можна вкластись у логіку, щоб змінити ціннісну позицію. Як, наприклад, - jsfiddle.net/hh719qex, якщо у вас кольоровий принтер. Якщо у вас всього 2 серії, ви також можете зробити такі речі, як встановлення textBaseline різних, якщо 2 бали знаходяться на 2 близько один від одного.
картопляні пілінги

4
це було для v1.0.2, як це зробити для v2.1.3? Структура об'єкта відрізняється в більш пізній версії.
techie_28

2
@potatopeelings Я тут використовував onCompleteзворотний виклик, але він також спрацьовує, коли курсор миші знаходиться на смужці діаграми, що призводить до того, що число блимає через redraw.Чи може це бути, якщо onAnimationComplete? Я не можу використовувати цей зворотний виклик із наявним кодом діаграми (див var chartBar. Внизу pastebin.com/tT7yTkGh )
techie_28

1
Мені потрібні як підказки інструментів, так і дані на верхній смужці мого графіка. Коли відображається наконечник інструменту, дані на верхній панелі перетворюються на білий колір, який видно на моїй прозорій підказці інструменту. Як я можу це виправити?
LJP

82

Ось оновлена ​​версія для Chart.js 2.3

23 вересня 2016: Відредагував мій код для роботи з v2.3 для обох типів рядка / смуги.

Важливо: Навіть якщо вам не потрібна анімація, не змінюйте параметр тривалості на 0, інакше ви отримаєте chartInstance.controller - невизначена помилка.

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: Неможливо прочитати властивість '0' undefined" при спробі цього на гістограмах. Чи бари використовують щось інше, ніж "модель.metaData [i] ._ model"?
Кріс Енселл

Це насправді var model = database._meta [i] .data [0] ._ model;
Фланамака

Це теж не повна правда. Я все ще отримую винятки. Спробуємо розібратися.
val

var model = database._meta [0] .data [i] ._ model; насправді.
Брайан

2
Схоже, це не так просто, як _meta [0]. Насправді об’єкт _meta не є масивом, він має єдиний елемент з номером як ключ. Я не можу з’ясувати обґрунтування того, яке число буде, тому я просто беру перший елемент, переглянувши список ключів, як-от так: var model = database._meta [Object.keys (skupac._meta) [0]] .data [i] ._ модель;
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}щоб зупинити мітки, що
анімували на курсі

1
Також зауважте, що якщо ви хочете приховати мітки, коли ви хочете щось від легенди, вам потрібно додати наступне перед циклом .filter(dataset => !dataset._meta[0].hidden)
forEach

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

Мені довелося користуватися Chart.defaults.global.tooltips.enabled = false;. Проблема з цим рішенням полягає в тому, що afterDrawфункція викликається сотні разів, ймовірно, генеруючи накладні витрати процесора. І все-таки це єдина відповідь на даний момент без блимань. Якщо вам потрібна краща візуалізація для horizontalBarдіаграм, використовуйте ctx.textAlign = 'left'; ctx.textBaseline = 'middle';та ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev

набагато більш чисте та модульне рішення.
hadaytullah

20

Виходячи з відповіді @ Росса на Chart.js 2.0 і вище, мені довелося включити трохи налаштувань, щоб захиститись від випадку, коли висоти смуги надто вибрали межу шкали.

Приклад

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()наприкінці, але це не допомогло
techie_28

onCompleteзворотний виклик виконується , коли я ширяв на барі, який викликає перемальовування і текст відображається в blink.Would це те ж саме з onAnimationComplete, а? Я не можу використовувати onAnimationCompleteвиклик назад з мого існуючого коду (див var chartBarв нижній частині Pastebin. com / tT7yTkGh
techie_28

Чи можна зробити те ж саме в круговій діаграмі
Раві Хамбхаті

@RaviKhambhati Так, ви можете перевірити це у цій відповіді: stackoverflow.com/a/38797604/6402571
Hung Tran

17

Якщо ви використовуєте плагін chartjs-plugin-datalabels, тоді допоможуть наступні об’єкти параметрів коду

Переконайтеся, що ви імпортуєте import 'chartjs-plugin-datalabels';у свій файл машинопису або додаєте посилання <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
Ваша відповідь така проста і працює для мене. Дякую. Щасливе кодування.
Бендхем Маніканта

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. Я вважаю за краще це рішення, оскільки воно використовує систему підказок.
Тельмо Маркес

1
Це рішення для більш ранньої версії. Як досягти цього для останньої версії, тобто 2.1.3. Я використовував відповіді картоплі і Хуан Транг в onCompleteзворотному режимі анімації, але він спрацьовує навіть тоді, коли висить над гратами діаграми, що призводить до того, що текст перемальовується і дає небажаний ефект моргання. Я також спробував afterDraw& все це так само. не трапляється у скрипці, наданій картопляними пілінгами. Усі ідеї PLZ?
techie_28

6

З зразків chart.js (файл Chart.js-2.4.0 / sample / 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);
                    });
                }
            });
        }
    });

`` `


До цього я додав рядок для вирівнювання на горизонтальній смужковій діаграмі, виконуючи, якщо (chart.config.type == "horizontalBar"), то визначивши власну вертикальну прокладку 10 для вирівнювання по центру.
Джефф Біглі

6

Я рекомендую використовувати цей плагін: https://github.com/chartjs/chartjs-plugin-datalabels

Мітки можна додати до діаграм, просто імпортувавши плагін у файл js, наприклад:

import 'chartjs-plugin-datalabels'

І їх можна налаштувати за допомогою цих документів: https://chartjs-plugin-datalabels.netlify.com/options.html


2
Найпростіший, не вимагає "коду", просто налаштування за допомогою стандартного об'єкта "параметри". Head-up: мінімально необхідна версія charts.js - 2.7.0 , я посилався на 2.5.0 з CDN, і на графіках не було змін ...
GBU

@GBU що таке атрибут параметра ?.
Бхімбім

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);
    }
  });
};

Джанне, дякую за рішення, це виглядає чудово. Але в мене ситуація, коли мої значення насправді є великими (5 десяткових чисел), і коли розмір екрана невеликий або у мене багато діаграм, цифри знаходяться один на одного. Чи є якийсь спосіб зробити цю роботу відповідально? Мовляв, змусити числа обертатися, коли немає місця, як і мітки під смужкою?
Фітер

@PhiterFernandes Я думаю, що слід обертатися, перевіряючи поточний розмір екрана у функції modifyCtx та використовуючи ctx.rotate. Однак я не впевнений, як порівняти розмір значення з наявним простором, щоб визначити час обертання.
Janne Annala

Функція modifyCtx працює лише один раз, і не змінювати розмір, правда? Я перегляну вихідний код chart.js і побачу, де вони роблять обертання міток на осі x. Якщо я щось бачу, я спробую щось зробити і скажу вам тут, добре? =)
Фітер

Я знайшов щось у версії 2.3.0, рядок 7075. calculateTickRotationЦе всередині функції Scale. Я проаналізую це.
Фітер

5

З мого досвіду, коли ви включаєте плагін charter-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);
                }
            }
        }
    }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.