forked from jacktuck/node-chartjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
112 lines (88 loc) · 3.08 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const fs = require('fs')
const path = require('path')
const EventEmitter = require('events')
const { promisify } = require('util')
const { JSDOM } = require('jsdom')
const Canvas = require('canvas')
// resolve peer dependancy
const chartJSPath = path.dirname(require.resolve('chart.js'))
const chartJSSrc = fs.readFileSync(`${chartJSPath}/../dist/Chart.min.js`, 'utf-8')
class ChartJs extends EventEmitter {
constructor (width = 1000, height = 1000) {
super()
this.height = height
this.width = width
}
async makeChart (chartConfig) {
this._chart && this._chart.destroy()
const html = `<html>
<body>
<div id='chart-div' style='font-size:12; width:${this.width}; height:${this.height};'>
<canvas id='myChart' width=${this.width} height=${this.height}></canvas>
</div>
</body>
<script>${chartJSSrc}</script>
</html>`
const { window } = new JSDOM(html, {
features: {
FetchExternalResources: ['script'],
ProcessExternalResources: ['script'],
SkipExternalResources: false
},
runScripts: 'dangerously'
})
this.window = window
this.window.CanvasRenderingContext2D = Canvas.Context2d
chartConfig.options = chartConfig.options || {}
chartConfig.options.responsive = false
chartConfig.options.width = 400
chartConfig.options.height = 400
chartConfig.options.animation = false
this.chartConfig = chartConfig
this.canvas = this.window.document.getElementById('myChart')
this.ctx = this.canvas.getContext('2d')
return this
}
drawChart () {
this.emit('beforeDraw', this.window.Chart)
if (this.chartConfig.options.plugins) {
this.window.Chart.pluginService.register(this.chartConfig.options.plugins)
}
if (this.chartConfig.options.charts) {
for (const chart of this.chartConfig.options.charts) {
this.window.Chart.defaults[chart.type] = chart.defaults || {}
if (chart.baseType) {
this.window.Chart.controllers[chart.type] = this.window.Chart.controllers[chart.baseType].extend(chart.controller)
} else {
this.window.Chart.controllers[chart.type] = this.window.Chart.DatasetController.extend(chart.controller)
}
}
}
this._chart = this.window.Chart(this.ctx, this.chartConfig)
return this
}
toBlob (mime) {
const toBlobRearg = (mime, cb) => this.canvas.toBlob((blob, err) => cb(err, blob), mime)
return promisify(toBlobRearg)(mime)
.catch(console.error)
}
toBuffer (mime = 'image/png') {
return this.toBlob(mime)
.then(blob => new Promise((resolve, reject) => {
const reader = new this.window.FileReader()
reader.onload = function (){
const buffer = new Buffer(reader.result)
resolve(buffer)
}
reader.readAsArrayBuffer(blob)
}))
.catch(console.error)
}
toFile (path, mime = 'image/png') {
const writeFile = promisify(fs.writeFile)
return this.toBuffer(mime)
.then(blob => writeFile(path, blob, 'binary'))
.catch(console.error)
}
}
module.exports = ChartJs