英文:
Chart.js: how do I group labels in toolips?
问题
我正在从ng2-nvd3(基于D3)迁移项目到ng2-charts(基于Chart.js),因为ng2-nvd3不再维护。
我的应用程序有一个血压图表,显示收缩压和舒张压。在ng2-nvd3中,这两个值在工具提示中组合在一起。此外,渲染的日期之间有更多的间距。以下是它的外观截图。
这是将数据映射到UI可理解的代码:
// 获取最近30天的血压读数
this.bloodPressureService.last30Days().subscribe((bpReadings: any) => {
bpReadings = bpReadings.body;
this.bpReadings = bpReadings;
// https://stackoverflow.com/a/34694155/65681
this.bpOptions = { ...D3ChartService.getChartConfig() };
if (bpReadings.readings.length) {
this.bpOptions.title.text = bpReadings.period;
this.bpOptions.chart.yAxis.axisLabel = '血压';
let systolics, diastolics, upperValues, lowerValues;
systolics = [];
diastolics = [];
upperValues = [];
lowerValues = [];
bpReadings.readings.forEach(item => {
systolics.push({
x: new Date(item.timestamp),
y: item.systolic
});
diastolics.push({
x: new Date(item.timestamp),
y: item.diastolic
});
upperValues.push(item.systolic);
lowerValues.push(item diastolic);
});
this.bpData = [
{
values: systolics,
key: '收缩压',
color: '#673ab7'
},
{
values: diastolics,
key: '舒张压',
color: '#03a9f4'
}
];
// 设置y轴范围,比最大和最小值大10
this.bpOptions.chart.yDomain = [Math.min.apply(Math, lowerValues) - 10, Math.max.apply(Math, upperValues) + 10];
} else {
this.bpReadings.readings = [];
}
});
D3ChartService
定义如下:
declare const d3, nv: any;
/**
* ChartService 用于定义D3的图表配置
*/
export class D3ChartService {
static getChartConfig() {
const today = new Date();
const priorDate = new Date().setDate(today.getDate() - 30);
return {
chart: {
type: 'lineChart',
height: 200,
margin: {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x(d) {
return d.x;
},
y(d) {
return d.y;
},
useInteractiveGuideline: true,
dispatch: {},
xAxis: {
axisLabel: '日期',
showMaxMin: false,
tickFormat(d) {
return d3.time.format('%b %d')(new Date(d));
}
},
xDomain: [priorDate, today],
yAxis: {
axisLabel: '',
axisLabelDistance: 30
},
transitionDuration: 250
},
title: {
enable: true
}
};
}
}
它在HTML模板中渲染如下:
<nvd3 [options]="bpOptions" [data]="bpData" class="with-3d-shadow with-transitions"></nvd3>
在使用ng2-charts时,工具提示仅在我悬停在图表上的数据点上时显示。
是否可能使用Chart.js/ng2-charts将数据分组在工具提示中,以便显示特定日期的两个条目?
这是用于映射数据的代码:
// 获取最近30天的血压读数
this.bloodPressureService.last30Days().subscribe((bpReadings: any) => {
bpReadings = bpReadings.body;
this.bpReadings = bpReadings;
if (bpReadings.readings.length) {
this.bpOptions = {
plugins: {
legend: { display: true },
title: {
display: true,
text: bpReadings.period,
},
},
scales: {
y: {
beginAtZero: false,
},
x: {
beginAtZero: false,
},
},
};
const labels: any = [];
const systolics: any = [];
const diastolics: any = [];
const upperValues: any = [];
const lowerValues: any = [];
bpReadings.readings.forEach((item: IBloodPressure) => {
const timestamp = dayjs(item.timestamp).format('MMM DD');
labels.push(timestamp);
systolics.push({
x: timestamp,
y: item.systolic,
});
diastolics.push({
x: timestamp,
y: item.diastolic,
});
upperValues.push(item.systolic);
lowerValues.push(item.diastolic);
});
const datasets = [
{
data: systolics,
label: '收缩压',
},
{
data: diastolics,
label: '舒张压',
},
];
this.bpData = {
labels,
datasets,
};
// 设置y轴范围,比最大和最小值大10
this.bpOptions.scales = {
y: {
max: Math.max(...upperValues) + 10,
min: Math.min(...lowerValues) - 10,
},
};
} else {
this.bpReadings.readings = [];
}
});
它在HTML模板中渲染如下:
<canvas
baseChart
*ngIf="bpReadings?.readings && bpReadings?.readings?.length"
height="125"
[type]="'line'"
[data]="bpData"
[options]="bpOptions"
>
</canvas>
我还想知道如何稍微填充日期,以便图表有一些填充,数据点不会在X轴的两端。我尝试了以下内容,它似乎给我正确的日期。但是,添加后线条不会渲染。
this.bpOptions.scales = {
<details>
<summary>英文:</summary>
I'm migrating a project from [ng2-nvd3](https://github.com/krispo/ng2-nvd3) (based on D3) to [ng2-charts](http://valor-software.github.io/ng2-charts/) (based on Chart.js) because ng2-nvd3 is no longer maintained.
My app has a blood pressure chart that shows both systolic and diastolic entries. With ng2-nvd3, both values are grouped together in the tooltip. Also, the dates rendered have a bit more spacing in them. Here's a screenshot of what it looks like.
[![ng2-nvd3 graph][1]][1]
Here's the code to map the data to something the UI can understand:
```typescript
// Get blood pressure readings for the last 30 days
this.bloodPressureService.last30Days().subscribe((bpReadings: any) => {
bpReadings = bpReadings.body;
this.bpReadings = bpReadings;
// https://stackoverflow.com/a/34694155/65681
this.bpOptions = { ...D3ChartService.getChartConfig() };
if (bpReadings.readings.length) {
this.bpOptions.title.text = bpReadings.period;
this.bpOptions.chart.yAxis.axisLabel = 'Blood Pressure';
let systolics, diastolics, upperValues, lowerValues;
systolics = [];
diastolics = [];
upperValues = [];
lowerValues = [];
bpReadings.readings.forEach(item => {
systolics.push({
x: new Date(item.timestamp),
y: item.systolic
});
diastolics.push({
x: new Date(item.timestamp),
y: item.diastolic
});
upperValues.push(item.systolic);
lowerValues.push(item.diastolic);
});
this.bpData = [
{
values: systolics,
key: 'Systolic',
color: '#673ab7'
},
{
values: diastolics,
key: 'Diastolic',
color: '#03a9f4'
}
];
// set y scale to be 10 more than max and min
this.bpOptions.chart.yDomain = [Math.min.apply(Math, lowerValues) - 10, Math.max.apply(Math, upperValues) + 10];
} else {
this.bpReadings.readings = [];
}
});
The D3ChartService
is defined as follows:
declare const d3, nv: any;
/**
* ChartService to define the chart config for D3
*/
export class D3ChartService {
static getChartConfig() {
const today = new Date();
const priorDate = new Date().setDate(today.getDate() - 30);
return {
chart: {
type: 'lineChart',
height: 200,
margin: {
top: 20,
right: 20,
bottom: 40,
left: 55
},
x(d) {
return d.x;
},
y(d) {
return d.y;
},
useInteractiveGuideline: true,
dispatch: {},
xAxis: {
axisLabel: 'Dates',
showMaxMin: false,
tickFormat(d) {
return d3.time.format('%b %d')(new Date(d));
}
},
xDomain: [priorDate, today],
yAxis: {
axisLabel: '',
axisLabelDistance: 30
},
transitionDuration: 250
},
title: {
enable: true
}
};
}
}
It's rendered in the HTML template with:
<nvd3 [options]="bpOptions" [data]="bpData" class="with-3d-shadow with-transitions"></nvd3>
With ng2-charts, the tooltip only shows when I hover over the data points on the graph.
Is it possible to group the data in a tooltip with Chart.js/ng2-charts so it shows both entries for a particular day?
Here's the code used to map the data:
// Get blood pressure readings for the last 30 days
this.bloodPressureService.last30Days().subscribe((bpReadings: any) => {
bpReadings = bpReadings.body;
this.bpReadings = bpReadings;
if (bpReadings.readings.length) {
this.bpOptions = {
plugins: {
legend: { display: true },
title: {
display: true,
text: bpReadings.period,
},
},
scales: {
y: {
beginAtZero: false,
},
x: {
beginAtZero: false,
},
},
};
// this.bpOptions.chart.yAxis.axisLabel = 'Blood Pressure';
const labels: any = [];
const systolics: any = [];
const diastolics: any = [];
const upperValues: any = [];
const lowerValues: any = [];
bpReadings.readings.forEach((item: IBloodPressure) => {
const timestamp = dayjs(item.timestamp).format('MMM DD');
labels.push(timestamp);
systolics.push({
x: timestamp,
y: item.systolic,
});
diastolics.push({
x: timestamp,
y: item.diastolic,
});
upperValues.push(item.systolic);
lowerValues.push(item.diastolic);
});
const datasets = [
{
data: systolics,
label: 'Systolic',
},
{
data: diastolics,
label: 'Diastolic',
},
];
this.bpData = {
labels,
datasets,
};
// set y scale to be 10 more than max and min
this.bpOptions.scales = {
y: {
max: Math.max(...upperValues) + 10,
min: Math.min(...lowerValues) - 10,
},
};
} else {
this.bpReadings.readings = [];
}
});
It's rendered by the HTML template with:
<canvas
baseChart
*ngIf="bpReadings?.readings && bpReadings?.readings?.length"
height="125"
[type]="'line'"
[data]="bpData"
[options]="bpOptions"
>
</canvas>
I'm also curious to know how to pad the dates a bit, so the chart has some padding and the data points aren't at the very ends of the X axis.
I tried the following, which does seem to give me the correct dates. However, the lines don't render after I add it.
this.bpOptions.scales = {
y: { ... },
x: {
min: dayjs(labels[0]).subtract(1, 'day').format('MMM DD'),
max: dayjs(labels[labels.length - 1]).add(1, 'day').format('MMM DD'),
}
};
答案1
得分: 1
尝试添加到图表 bpOptions
interaction: {
mode: 'index',
intersect: false, // 如果为 true,则仅在鼠标位置与图表上的项目相交时才应用交互模式。
},
文档中有更多关于交互的信息 interaction modes
英文:
Try add to chart bpOptions
interaction: {
mode: 'index',
intersect: false, // if true, the interaction mode only applies when the mouse position intersects an item on the chart.
},
more interactions in docs interaction modes
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论