如何在chart.js图中做出差距?

时间:2017-05-09 06:05:11

标签: chart.js

这是我需要创建的必需图表。谁能告诉我如何在y轴和x轴的第一个标签(1月)之间创建差距?

enter image description here

2 个答案:

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

<强>ᴅᴇᴍᴏ

&#13;
&#13;
// 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;
&#13;
&#13;

答案 1 :(得分:0)

您可以通过指定比例的最小值和最大值来创建间隙。

在您的情况下, X 时间刻度 Y 线性刻度。因此,每个人都有自己的附加选项。

如果确定数据的最小值和最大值,则可以在比例范围中添加偏移量。例如[min - 123,max + 123],考虑到偏移量为123。

我创建了一个使用Chart.js的Angular组件。 Angular组件,因为这似乎是要求。此外,在编辑问题之前放置了angular标记。如果不需要Angular组件,则在createChart()内找到重要的逻辑,大多数代码与Chart.js相关,而与Angular相关。

请注意,以下代码是用TypeScript编写的,因为这是编写Angular应用程序的推荐方法。

<强>依赖关系

  • Graph.js: npm install --save chart.js
  • Graph.js typings: typings install --save --global dt~chartjs
  • 时刻: npm install --save moment

图表数据模型

图表数据集的建模如下:

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;
          }
        }
      }],

这是一个时间轴,其范围由timeXMintimeXMax确定。这些是通过查找所有数据集的最小值和最大值来计算的。然后添加一个月的偏移量,分别为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值的标签。

说明::组件生命周期

组件具有widthheight输入,以便设置<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 scaleYtime scale{ x, y },因此数据格式为xy是日期类型,x是数字。 yChart.js属性由X识别,并分别分配到Yconst 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()创建一个从上到下过渡的渐变。