Vue Chart.js - простая точка / линия на гистограмме

Мне нужно добавить простую точку / вертикальную линию на мою диаграмму bar, которая имеет динамическое значение X и 0 для значения Y. Предварительный просмотр того, что мне нужно (красная точка):

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

Где зеленые значения динамические.

Предварительный просмотр моего текущего состояния:

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

Где 3.30 должна быть координата X точки - [3.30, 0].

Я использую диаграмму Vue для диаграмм, и я попытался создать смешанный с bar и scatter, но scatter требует type: 'linear', поскольку это xAxis мне не подходит для диаграммы bar.

Поэтому я попробовал использовать chartjs-plugin-annotation, и это box тип, который принимает "координаты", но проблема здесь в том, что значение X должно быть фиксированным значением по оси X (объект labels). Если я поставлю для оси X [3,0], это будет работать, но если есть десятичное число, например [3.5, 0], это не сработает.


  // data
  options: {
    responsive: true,
    maintainAspectRatio: false,
    legend: {
      display: false
    },
    scales: {
      yAxes: [{
        ticks: {
          min: 0,
          max: 1,
          stepSize: 0.1
        }
      }]
    }
  }

  // computed 
  labels: [1, 2, 3, 4, 5, 6], // fixed value, there are always 6 bars
  datasets: [
    {
      label: 'Values',
      backgroundColor: '#f89098',
      data: this.tableInputValues // array of decimal values
    }
  ]

Итак, мой вопрос заключается в том, как разместить «простую» точку или вертикальную линию на гистограмме Chart.js, где точка имеет динамическое значение для оси X -> [динамическое значение, 0].

К вашему сведению - это о ожидаемом значении


person Vucko    schedule 06.12.2018    source источник
comment
Вы умеете создавать скрипку?   -  person Krzysztof Atłasik    schedule 11.12.2018
comment
@ KrzysztofAtłasik вот пример. Итак, теперь предположим, что хотелось бы иметь точку на xAxis или вертикальную линию, где значение xAxes является динамическим (например, 3,9 или 2,75).   -  person Vucko    schedule 13.12.2018
comment
@Vucko, Привет, не могли бы вы описать вашу проблему, например, какие данные по осям x и y использовались для описания? Пример на вашем снимке: ось x используется для описания значений, а ось y - для частоты (от 0,0 до 1,0), но в вашей скрипке ось x не связана с вашей проблемой. И какие данные, которые вы хотите отобразить точкой на оси X, описывают? Я думаю, вы можете использовать type: 'buddle' со смешанным типом для своей проблемы, но я надеюсь подробное описание.   -  person huynhsamha    schedule 15.12.2018


Ответы (2)


Насколько я понимаю, Vue Chart работает с использованием холста (как показано на демонстрационной странице).
Итак я предлагаю получить узел холста, представляющий диаграмму в вашей модели DOM, и динамически записать желаемую точку. Например:

var c = document.getElementById("bar-chart");   //hereby assuming canvas named "bar-chart"
var ctx = c.getContext("2d");
ctx.fillStyle = "#ff0000";                     //red color for the dot
ctx.beginPath();
let yPosition = c.height - 5;                 //fixed y position
let xPosition = 35;                          //that's the dynamic expected value
ctx.arc(xPosition, yPosition, 2.5, 0, 2 * Math.PI);
ctx.fill();

Здесь вы найдете демонстрацию, показывающую, как этого добиться с помощью Vue. В этом сценарии вам нужно обернуть код, чтобы нарисовать точку на холсте в afterDraw крючок. Этот хук нужно прикрепить к компоненту диаграммы как плагин, например:

...
mounted () { 
   //adding the plugin to draw the red dot
   this.addPlugin({
    id: 'chart-plugin',
    afterDraw: function (chart) {
       var c = chart.canvas;   
       var ctx = c.getContext("2d");
       ctx.fillStyle = "#ff0000";                     
       ctx.beginPath();
       let xPosition = 742; //x positioning to be calculated according to your needs
       let yPosition = c.height - 28;                                       
       ctx.arc(xPosition, yPosition, 3, 0, 2 * Math.PI);
       ctx.fill();
    }
  });

  //actual chart rendering
  this.renderChart({ 
    ...
  });
}
...

Для полноты картины здесь вы найдете список всех доступных хуков API плагина Chart.js.

person P3trur0    schedule 10.12.2018
comment
Буду признателен, если вы измените ответ для решения Vue. Спасибо - person Vucko; 10.12.2018
comment
@Vucko, держи. - person P3trur0; 12.12.2018
comment
Спасибо за обновление, сообщу, когда буду тестировать. - person Vucko; 13.12.2018
comment
@Vucko пожалуйста. Здесь вы найдете ваш пример JsFiddle, обновленный с помощью ловушки afterDraw: jsfiddle.net/jh4aobw8 - person P3trur0; 13.12.2018
comment
Спасибо за ответ. Однако вы также можете изменить для использования плагина vue-chart, это Помогу. - person Vucko; 16.12.2018
comment
@Vucko пожалуйста. Пример с плагином vue-chart находится здесь: codepen.io/anon/pen/oJXVRx - person P3trur0; 16.12.2018
comment
Отлично! Tnx за помощь. Ваше здоровье! - person Vucko; 16.12.2018

Это мое решение вашей проблемы https://jsfiddle.net/huynhsamha/e54djwxp/

А это скриншот с результатом

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

В своем решении я использую type="line", а также ось x и ось y с type="linear". Я также добавляю свойство options в <chart> для использования options в ChartJS

<div id="vue">
  <chart type="line" :data="data" :options="options"></chart>
</div>

options настроит ось x и ось y для отображения точек данных и ожидаемого значения:

      options: {
        scales: {
            xAxes: [{
            type: 'linear',
            ticks: {
                min: 1,
                max: 6,
                stepSize: 1
            }
          }],
           yAxes: [{
            type: 'linear',
            ticks: {
                min: 0,
                max: 1,
                stepSize: 0.1
            }
            }]
        }
      }

А у data будет 2 datasets. Первый - это точки данных, используйте тип line, а второй - ожидаемое значение, использующее тип bubble.

      data: {
        datasets: [{
            label: 'Frequency Data',
            data: dataPoints.map(({ val, freq }) => ({
                x: val,
              y: freq
            })),
            backgroundColor: 'rgba(72, 202, 59, 0.4)',
            borderColor: 'rgba(72, 202, 59, 1)'
        }, {
            label: 'Expected Value',
            type: 'bubble',
            data: [{ 
                x: expectedValue, 
              y: 0, 
              r: 8 // radius
            }],
            backgroundColor: 'rgba(255, 68, 0, 0.4)',
            borderColor: 'rgba(255, 68, 0, 1)'
        }]
        },

В datasets у нас есть dataPoints и expectedValue, они будут извлечены из API для получения ваших точек данных. Я также моделирую простой API для точек данных:

// simulate the API to get data points
const retrieveData = () => [
    { val: 1, freq: 0.15 },
    { val: 2, freq: 0.25 },
    { val: 3, freq: 0.3 },
    { val: 4, freq: 0.2 },
    { val: 5, freq: 0.1 },
    { val: 6, freq: 0.45 }
]


// fetch your data here, return array of JSON { val, freg }
const dataPoints = retrieveData() || [];

// calculate expected value = sum( val * freq ) each i in dataPoints
const expectedValue = dataPoints.reduce((cur, { val, freq }) => cur + val * freq, 0).toFixed(4);

Вы можете запустить сниппет или запустить скрипт https://jsfiddle.net/huynhsamha/e54djwxp/92/ < / а>

<script async src="//jsfiddle.net/huynhsamha/e54djwxp/92/embed/js,html,css,result/dark/"></script>

person huynhsamha    schedule 15.12.2018
comment
Tnx за ответ, действительно хорошее решение. - person Vucko; 16.12.2018