Vue Chart.js - простая точка/строка на гистограмме
Мне нужно было бы добавить простую точечную/вертикальную линию на мою bar
которая имеет динамическое значение X, и 0 для значения Y. Предварительный просмотр того, что мне нужно (красная точка):
Где зеленые значения являются динамическими.
Предварительный просмотр моего текущего состояния:
Где 3.30 должно быть координатой X точки - [3.30, 0].
Я использую диаграмму Vue для диаграмм, и я попытался создать смешанную scatter
с 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].
К вашему сведению - это об ожидаемой стоимости
Ответы
Ответ 1
Насколько я понимаю, Vue Chart работает с использованием canvas (как видно на демонстрационной странице).
Итак, мое предложение здесь состоит в том, чтобы извлечь узел холста, представляющий диаграмму в вашем 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 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.
Ответ 2
Это мое решение вашей проблемы 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
, оно будет dataPoints
из 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>