答案 0 :(得分:1)
您可以通过创建图表插件来实现这一目标,如此......
Chart.plugins.register({
afterUpdate: function(chart) {
var dataset = chart.config.data.datasets[0];
var offset = 27;
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[0].data[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
}
});
<强>ᴅᴇᴍᴏ强>
// register plugin
Chart.plugins.register({
afterUpdate: function(chart) {
var dataset = chart.config.data.datasets[0];
var offset = 27; //set that suits the best
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[0].data[i]._model;
model.x += offset;
model.controlPointNextX += offset;
model.controlPointPreviousX += offset;
}
}
});
// generate chart
var ctx = document.querySelector('#canvas').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Line Chart',
data: [10, 20, 18, 16, 19, 22],
backgroundColor: 'rgba(75,192,192, 0.4)',
borderColor: '#4bc0c0',
pointBackgroundColor: 'black',
tension: 0,
}]
},
options: {
responsive: false,
scales: {
xAxes: [{
gridLines: {
offsetGridLines: true,
display: false
}
}],
yAxes: [{
ticks: {
beginAtZero: true
},
gridLines: {
display: false
}
}]
}
}
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="canvas" width="340" height="180"></canvas>
&#13;
答案 1 :(得分:0)
您可以通过指定比例的最小值和最大值来创建间隙。
在您的情况下, X 为时间刻度, Y 为线性刻度。因此,每个人都有自己的附加选项。
如果确定数据的最小值和最大值,则可以在比例范围中添加偏移量。例如[min - 123,max + 123],考虑到偏移量为123。
我创建了一个使用Chart.js的Angular组件。 Angular组件,因为这似乎是要求。此外,在编辑问题之前放置了angular
标记。如果不需要Angular组件,则在createChart()
内找到重要的逻辑,大多数代码与Chart.js
相关,而与Angular相关。
请注意,以下代码是用TypeScript
编写的,因为这是编写Angular应用程序的推荐方法。
<强>依赖关系强>
图表数据模型
图表数据集的建模如下:
export interface GraphDataSet {
label: string;
data: { x: any, y: any }[];
}
其中label
是描述此数据集的标签。
data
是描述X轴和Y轴位置的x-y对数组。
请注意,一个图表可以包含多个数据集。该模型对应于一个数据集。因此,图表组件将接收一组数据集模型。
<强>组件强>
import {AfterViewChecked, Component, ElementRef, Input, OnInit, ViewChild} from '@angular/core';
import 'chart.js';
import Chart from 'chart.js';
import {GraphDataSet} from './GraphDataSet';
import * as moment from 'moment';
@Component({
selector: 'graph-line',
template: `<canvas #canvas [width]="width" [height]="height"></canvas>`
})
export class GraphLineComponent implements OnInit, AfterViewChecked {
private _canvas: ElementRef;
private _dataSets: GraphDataSet[];
private _chart: Chart;
@Input()
width: number;
@Input()
height: number;
@Input()
public dataSets: GraphDataSet[];
@ViewChild('canvas')
public canvas: ElementRef;
constructor() {
}
ngOnInit() {
}
ngAfterViewChecked(): void {
if (this.canvas !== this._canvas || this.dataSets !== this._dataSets) {
this._canvas = this.canvas;
this._dataSets = this.dataSets;
setTimeout(() => this.createChart(), 0);
}
}
private createChart() {
const ctx = this.canvas.nativeElement.getContext('2d');
// create background linear gradient (top-to-bottom)
const backgroundGradient = ctx.createLinearGradient(this.width / 2, 0, this.width / 2, this.height);
backgroundGradient.addColorStop(0, '#5ebb95');
backgroundGradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
// create default settings that can be used to style the dataset
const defaultDataSetSettings = {
backgroundColor: backgroundGradient,
borderColor: '#5ebb95',
borderWidth: 1,
pointBackgroundColor: '#5ebb95',
tension: 0,
pointBorderWidth: 7,
pointHoverBorderWidth: 10
};
const data = {
datasets: this.dataSets.map(dataSet => Object.assign({}, defaultDataSetSettings, dataSet))
};
const xMin = this.getXMin(this.dataSets);
const xMax = this.getXMax(this.dataSets);
const timeXMin = xMin.subtract(1, 'months');
const timeXMax = xMax.add(1, 'months');
this._chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: false,
tooltips: {
callbacks: {
title: (item, chartData) => item.map(i => chartData.datasets[i.datasetIndex].label),
label: (item, chartData) => item.yLabel + ' on ' + moment(item.xLabel).format('LL')
}
},
scales: {
xAxes: [{
type: 'time',
position: 'bottom',
gridLines: {
display: false
},
time: {
displayFormats: {
month: 'MMM'
},
unit: 'month',
min: timeXMin,
max: timeXMax
},
ticks: {
callback: (value, index, values) => {
const date = values[index];
console.log(date.diff(xMin, 'months'));
return date.diff(xMin, 'days') <= 0 || date.diff(xMax, 'days') >= 0 ? null : value;
}
}
}],
yAxes: [{
type: 'linear',
position: 'left',
gridLines: {
borderDash: [10, 10],
zeroLineWidth: 0
},
ticks: {
min: 0,
fixedStepSize: 200,
callback: (value) => value === 0 ? null : value
}
}]
}
}
});
}
private getXMin(dataSets: GraphDataSet[]) {
let min: Date = null;
dataSets.forEach(dataSet => {
dataSet.data.forEach(data => {
if (!min || data.x < min) {
min = data.x;
}
});
});
return moment(min);
}
private getXMax(dataSets: GraphDataSet[]) {
let max: Date = null;
dataSets.forEach(dataSet => {
dataSet.data.forEach(data => {
if (!max || data.x > max) {
max = data.x;
}
});
});
return moment(max);
}
}
<强>用法强>
<graph-line [dataSets]="dataSets" [width]="500" [height]="300"></graph-line>
数据强>
this.dataSets = [
{
label: 'My Monthly Report',
data: [
{x: Date.parse('2017-01-10'), y: 500},
{x: Date.parse('2017-02-15'), y: 700},
{x: Date.parse('2017-03-10'), y: 600},
{x: Date.parse('2017-04-20'), y: 590},
{x: Date.parse('2017-05-30'), y: 610},
{x: Date.parse('2017-06-25'), y: 800}
]
}
];
说明:: X轴
xAxes: [{
type: 'time',
position: 'bottom',
gridLines: {
display: false
},
time: {
displayFormats: {
month: 'MMM'
},
unit: 'month',
min: timeXMin,
max: timeXMax
},
ticks: {
callback: (value, index, values) => {
const date = values[index];
console.log(date.diff(xMin, 'months'));
return date.diff(xMin, 'days') <= 0 || date.diff(xMax, 'days') >= 0 ? null : value;
}
}
}],
这是一个时间轴,其范围由timeXMin
和timeXMax
确定。这些是通过查找所有数据集的最小值和最大值来计算的。然后添加一个月的偏移量,分别为xMin.subtract(1, 'months')
和xMax.add(1, 'months')
。
time.displayFormats.month
会将月份显示为标签。
time.unit: 'month'
会将比例分成几个月,然后使用time.displayFormats.month
将每个单位格式化为标签。
ticks.callback
用于删除[xMin, xMax]
之外的时间单位的标签,这是所有数据集的最小值和最大值。
说明:: Y轴
yAxes: [{
type: 'linear',
position: 'left',
gridLines: {
borderDash: [10, 10],
zeroLineWidth: 0
},
ticks: {
min: 0,
fixedStepSize: 200,
callback: (value) => value === 0 ? null : value
}
}]
这是线性刻度。
gridLines.borderDash
为线性刻度上的每个刻度创建虚线。
ticks.min: 0
指定比例从零开始。
ticks.fixedStepSize: 200
指定每个刻度线刻度将为200。
ticks.callback
删除0值的标签。
说明::组件生命周期
组件具有width
和height
输入,以便设置<canvas>
的大小,dataSets
是其模板中唯一的元素。
另一个输入是Chart.js
,它是传递给ngAfterViewChecked()
的实际数据。
该组件具有<canvas>
挂钩,这意味着可以检查更改,例如,是否有任何输入已更改或setTimeout(() => this.createChart(), 0);
元素由于某种原因而发生了更改。如果我们看到某些输入已经改变,那么我们就像这样setTimeout()
创建图表。使用this.dataSets = [
{
label: 'My Monthly Report',
data: [
{x: Date.parse('2017-01-10'), y: 500},
{x: Date.parse('2017-02-15'), y: 700},
{x: Date.parse('2017-03-10'), y: 600},
{x: Date.parse('2017-04-20'), y: 590},
{x: Date.parse('2017-05-30'), y: 610},
{x: Date.parse('2017-06-25'), y: 800}
]
}
];
因为此时我们无法更改任何参数,并且为了安全起见,处理在单独的调用堆栈上完成。
说明::数据
X
由于linear scale
是Y
且time scale
是{ x, y }
,因此数据格式为x
。 y
是日期类型,x
是数字。 y
和Chart.js
属性由X
识别,并分别分配到Y
和const ctx = this.canvas.nativeElement.getContext('2d');
// create background linear gradient (top-to-bottom)
const backgroundGradient = ctx.createLinearGradient(this.width / 2, 0, this.width / 2, this.height);
backgroundGradient.addColorStop(0, '#5ebb95');
backgroundGradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
// create default settings that can be used to style the dataset
const defaultDataSetSettings = {
backgroundColor: backgroundGradient,
borderColor: '#5ebb95',
borderWidth: 1,
pointBackgroundColor: '#5ebb95',
tension: 0,
pointBorderWidth: 7,
pointHoverBorderWidth: 10
};
const data = {
datasets: this.dataSets.map(dataSet => Object.assign({}, defaultDataSetSettings, dataSet))
};
比例。
说明::数据集设置
datasets: this.dataSets.map(dataSet => Object.assign({}, defaultDataSetSettings, dataSet))
此代码的目的是创建可与数据集关联的默认设置。默认数据集设置使用用户定义的设置进行扩展,如backgroundColor
。
在设计中ctx.createLinearGradient(...)
是一个渐变,因此使用画布上下文fetchBoard()
创建一个从上到下过渡的渐变。