前言

项目需要使用chart.js插件,由于项目是使用angular开发,那么我第一步就是先把chart.js改造成angular组件来使用。

本项目代码都可以在github上下载:项目git地址

angular改造

1、搭建angular项目步骤省略了,可以自行查询ng官方文档

2、创建一个chart-js的组件

  1. ng g c chart-js

chart-js.component.html

  1. <div style="display: block; height: 100%">
  2. <canvas #canvas></canvas>
  3. </div>

chart-js.component.ts

  1. import {
  2. Component,
  3. OnInit,
  4. ViewChild,
  5. ElementRef,
  6. AfterViewInit,
  7. Input,
  8. OnChanges,
  9. SimpleChanges,
  10. OnDestroy
  11. } from "@angular/core";
  12. import "chart.js";
  13. declare var window: any;
  14. @Component({
  15. selector: 'chart-js',
  16. templateUrl: './chart-js.component.html',
  17. styleUrls: ['./chart-js.component.css']
  18. })
  19. export class ChartJsComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy {
  20. @ViewChild("canvas") canvas: ElementRef;
  21. @Input() config;
  22. private chart;
  23. constructor() { }
  24. ngOnInit() {
  25. }
  26. // 子组件加载完成后,渲染图标
  27. ngAfterViewInit() {
  28. this.render();
  29. }
  30. // 渲染图表
  31. render() {
  32. this.chart = new window.Chart(
  33. this.canvas.nativeElement.getContext("2d"),
  34. this.config
  35. );
  36. this.chart.height = "100%";
  37. }
  38. // 判断Input参数config 是否变化,如果变化,触发更新绘图
  39. ngOnChanges({ config }: SimpleChanges) {
  40. if (config && !config.isFirstChange()) {
  41. this.destroyChart();
  42. this.render();
  43. }
  44. }
  45. // 销毁chart
  46. ngOnDestroy() {
  47. this.destroyChart();
  48. }
  49. // 销毁chart主体
  50. destroyChart() {
  51. if (this.chart) {
  52. this.chart.destroy();
  53. this.chart = undefined;
  54. }
  55. }
  56. }

好了angular组件就这样改造完成了,接下来我们看下如何调用把

  1. // html
  2. <div style="width:50%;margin:0 auto;">
  3. <chart-js [config]="config"></chart-js>
  4. </div>
  5. // ts
  6. // 一份简单的配置,后续会详细解释配置的含义
  7. this.config = {
  8. type: 'bar',
  9. data: {
  10. labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
  11. datasets: [{
  12. label: '# of Votes',
  13. data: [12, 19, 3, 5, 2, 3],
  14. backgroundColor: [
  15. 'rgba(255, 99, 132, 0.2)',
  16. 'rgba(54, 162, 235, 0.2)',
  17. 'rgba(255, 206, 86, 0.2)',
  18. 'rgba(75, 192, 192, 0.2)',
  19. 'rgba(153, 102, 255, 0.2)',
  20. 'rgba(255, 159, 64, 0.2)'
  21. ],
  22. borderColor: [
  23. 'rgba(255,99,132,1)',
  24. 'rgba(54, 162, 235, 1)',
  25. 'rgba(255, 206, 86, 1)',
  26. 'rgba(75, 192, 192, 1)',
  27. 'rgba(153, 102, 255, 1)',
  28. 'rgba(255, 159, 64, 1)'
  29. ],
  30. borderWidth: 1
  31. }]
  32. },
  33. options: {
  34. scales: {
  35. yAxes: [{
  36. ticks: {
  37. beginAtZero:true
  38. }
  39. }]
  40. },
  41. onHover(event, elements) {
  42. console.log(event,elements);
  43. },
  44. }
  45. }

看下效果吧:

配置详解

具体配置可以参考下面链接,非常全面

Chart.js中文文档

配置一个复合图表

经常可以看到一个数据表中包含几种方式的展示具体看图:



既有柱状图也有折线图。像这样的该如何进行配置呢?

只需要在dataset里面新增一种数据类型并制定相应的type即可,具体如下

  1. datasets: [
  2. {
  3. label: '# of Votes',
  4. data: [12, 19, 3, 5, 2, 3],
  5. backgroundColor: [
  6. 'rgba(255, 99, 132, 0.2)',
  7. 'rgba(54, 162, 235, 0.2)',
  8. 'rgba(255, 206, 86, 0.2)',
  9. 'rgba(75, 192, 192, 0.2)',
  10. 'rgba(153, 102, 255, 0.2)',
  11. 'rgba(255, 159, 64, 0.2)'
  12. ],
  13. borderColor: [
  14. 'rgba(255,99,132,1)',
  15. 'rgba(54, 162, 235, 1)',
  16. 'rgba(255, 206, 86, 1)',
  17. 'rgba(75, 192, 192, 1)',
  18. 'rgba(153, 102, 255, 1)',
  19. 'rgba(255, 159, 64, 1)'
  20. ],
  21. borderWidth: 1
  22. },
  23. {
  24. type: "line", // 将此数据集类型变为折线图
  25. label: "Line Dataset",
  26. data: [3, 5, 7, 16]
  27. }
  28. ]

查看完整配置代码

chart.js 插件编写

插件扩展分为全局插件和内联插件

【内联插件】

插件也可以直接在图表插件配置(即内联插件)中定义

  1. var chart = new Chart(ctx, {
  2. plugins: [
  3. {
  4. beforeInit: function(chart, options) {
  5. //..
  6. }
  7. }
  8. ]
  9. });

【全局插件】

插件可以在全局范围内注册,应用于所有图表(即全局插件)

  1. Chart.pluginService.register({
  2. // plugin implementation
  3. });

【编写一个插件】

回顾下上面我们画的图表

如果这个时候产品跟我们说,想在这个图表上添加一个背景色,且背景色可以设置。

我们赶紧翻到柱状/条形图(Bar)的配置这里查看,发现并没有这个配置项,只能对各个柱状/条形图填充色。并不能对整个背景填充颜色

怎么办?编写插件吧。

查看下文档发现插件提供了一些钩子函数给我们:

那么我们开始正式编写插件

  1. beforeDraw: function(chartInstance) {
  2. // chartInstance === 画布实例
  3. // 首先我们去获取配置表,看是否配置了chartAreaBackground,如果没有配置则不执行
  4. if (!chartInstance.options.chartAreaBackground) return;
  5. var ctx = chartInstance.chart.ctx; // 获取画布上下文
  6. var chartArea = chartInstance.chartArea; // 画布区域
  7. var left = chartArea.left;
  8. var right = chartArea.right;
  9. var yOptions = chartInstance.scales["y-axis-0"];
  10. var yAxesTop = yOptions.paddingTop;
  11. var yAxesBottom = yOptions.paddingBottom;
  12. var top = chartArea.top + yAxesTop;
  13. var bottom = chartArea.bottom - yAxesBottom;
  14. var width = right - left; // 获取到画布宽度
  15. var height = bottom - top; // 获取画布的高度
  16. ctx.fillStyle = chartInstance.options.chartAreaBackground; // 获取背景色
  17. ctx.fillRect(left, top, width, height); // 举行填充
  18. }

如果对区域的位置不清楚的可以看下面的标注:

插件编写好了。如何使用呢?

插件里面通过判断chartInstance.options.chartAreaBackground 这个是否配置。那么很明显,我们对这个进行配置就可以了

  1. options:{
  2. chartAreaBackground:'#f5f5f5'
  3. }

再来看下效果:



灰色背景色已经出现了。说明内联插件我们已经配置成功了。

【把上面的插件改造成全局插件】

新建文件 chart-plugin.ts

  1. import * as Chart from "chart.js";
  2. const drawBgColorFactory = function (Chart) {
  3. const drawBgColor = {
  4. beforeDraw: function(chartInstance) {
  5. // chartInstance === 画布实例
  6. console.log(chartInstance);
  7. // 首先我们去获取配置表,看是否配置了chartAreaBackground,如果没有配置则不执行
  8. if (!chartInstance.options.chartAreaBackground) return;
  9. var ctx = chartInstance.chart.ctx; // 获取画布上下文
  10. var chartArea = chartInstance.chartArea; // 画布区域
  11. var left = chartArea.left;
  12. var right = chartArea.right;
  13. var yOptions = chartInstance.scales["y-axis-0"];
  14. var yAxesTop = yOptions.paddingTop;
  15. var yAxesBottom = yOptions.paddingBottom;
  16. var top = chartArea.top + yAxesTop;
  17. var bottom = chartArea.bottom - yAxesBottom;
  18. var width = right - left; // 获取到画布宽度
  19. var height = bottom - top; // 获取画布的高度
  20. ctx.fillStyle = chartInstance.options.chartAreaBackground; // 获取背景色
  21. ctx.fillRect(left, top, width, height); // 举行填充
  22. }
  23. };
  24. Chart.pluginService.register(drawBgColor);
  25. };
  26. drawBgColorFactory(Chart);

这样我们就在全局注册成功了

小结

那么至此全局插件,局部插件我们都已经实现了,如果想要实现更加复杂的插件,则需要在项目中更加深入的去学习chart.js插件

chart.js angular组件封装(ng6)、实战配置、插件编写的更多相关文章

  1. js日志组件封装

    js日志组件~~ 1 function Logger(level) { if (!(this instanceof Logger)) { return new Logger(); } var ERRO ...

  2. Vue.js 自定义组件封装实录——基于现有控件的二次封装(以计时器为例)

    在本人着手开发一个考试系统的过程中,出现了如下一个需求:制作一个倒计时的控件显示在试卷页面上.本文所记录的就是这样的一个过程. 前期工作 对于这个需求,自然我想到的是有没有现成的组件可以直接使用(本着 ...

  3. 04.ElementUI源码学习:组件封装、说明文档的编写发布

    0x00.前言 书接上文.项目经过一系列的配置,开发脚手架已经搭建完毕.接下来开始封装自定义组件.并基于 markdown 文件生成文档和演示案例. 后续文章代码会根据篇幅,不影响理解的情况下进行部分 ...

  4. calendar.js(日历组件封装)

    最近一直闲来无事,便寻思着做一下自己的个人项目,也想说能使用现在比较流行的一些mvvm框架来做,于是就选用了这样的一个技术栈vue2.0+vue-router+vuex+webpack来做,做得也是多 ...

  5. vue2.0项目 calendar.js(日历组件封装)

    最近一直闲来无事,便寻思着做一下自己的个人项目,也想说能使用现在比较流行的一些mvvm框架来做,于是就选用了这样的一个技术栈vue2.0+vue-router+vuex+webpack来做,做得也是多 ...

  6. vue.js table组件封装

    table组件 和 分页组件来自iview,在这里我根据公司业务再次做了一次封装,使用slot进行内容分发,可以随意放置input输入框和button按钮 ,再使用props向子组件传递参数,使用em ...

  7. Angular指令封装jQuery日期时间插件datetimepicker实现双向绑定

    一放假就高产似母猪了. 00.混乱的前端界 Angular1.x确实是个学习成本很高的框架,刚开始实习那会儿,前端啥也不懂,工头说用Angular,我们这群小弟也只能硬着头皮学.在这之前,前端的东西大 ...

  8. Hapi+MySql项目实战配置插件-加载文件渲染母版(三)

    加载插件 一般在其它node框架下,我们安装好插件直接require('插件')就能正常使用了,但是在Hapi下我们必须要Server.register()方法,才能正常使用插件.举个例子: serv ...

  9. 原生JS面向对象思想封装轮播图组件

    原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能 ...

随机推荐

  1. MT【308】投影的定义

    已知向量$\overrightarrow{a},\overrightarrow{b}$满足:$|\overrightarrow{a}|=2$,向量$\overrightarrow{b}$与$\over ...

  2. MT【286】最佳有理逼近

    2017北大优秀中学生夏令营已知$\omega $是整系数方程$x^2+ax+b=0$的一个无理数根, 求证:存在常数$C$,使得对任意互质的正整数$p,q$都有$$|\omega-\dfrac{p} ...

  3. BM算法

    BM算法 用来求解一个数列的递推式. 即给定\(\{x_i\}\)求解一个\(\{a_i\}\),满足\(|a|=m,x_n=\sum_{i=1}^ma_i*x_{n-i}\). 考虑增量法构造. 假 ...

  4. luogu3233 世界树 (虚树)

    反正肯定要建虚树,考虑建完之后怎么做 先随便dp一下算出来距离某点最近的询问点mi[x](因为有的虚树上的点它不是询问点嘛) 那我们对于某条链x到fa[x]上的非虚树上的点(包括他们的非虚树上的孩子) ...

  5. Picture POJ - 1177 (扫描线)

    扫描线求周长,可以看成两条线,一条扫x轴,一条扫y轴,然后这两天线扫过去的 周长加起来,就是周长了 #include<map> #include<set> #include&l ...

  6. NOIp2018 复习笔记

    其实也没什么用啦,只是来占个坑 OI知识 3367 [模板]并查集 就这么做啊 没什么其他的 就是可以做tarjan LCA和Kruskal的操作 //关键函数 int getfa(int t) { ...

  7. [SHOI2001]化工厂装箱员(dp?暴力:暴力)

    118号工厂是世界唯一秘密提炼锎的化工厂,由于提炼锎的难度非常高,技术不是十分完善,所以工厂生产的锎成品可能会有3种不同的纯度,A:100%,B:1%,C:0.01%,为了出售方便,必须把不同纯度 ...

  8. 纯原生JS大图轮播

    CSS部分: CSS: <style type="text/css"> #banner { position: relative; width: 500px; heig ...

  9. 第三节,使用OpenCV 3处理图像(模糊滤波、边缘检测)

    一 不同色彩空间的转换 OpenCV中有数百种关于在不同色彩空间之间转换的方法.当前,在计算机中有三种常用的色彩空间:灰度,BGR以及HSV(Hue,Saturation,Value). 灰度色彩空间 ...

  10. C 线程学习记录

    "互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域. 这时的解决方法,就是在门口挂n把钥匙.进去的人就取一把钥匙,出来时再把钥匙挂 ...