/
SimplePie.js
79 lines (69 loc) · 2.63 KB
/
SimplePie.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
import Chart from './Chart'
import sortBy from 'lodash/sortBy'
/**
* @typedef {Object} Chart
* @property {Object} layout
* @property {Object} plot
* @property {Object} legend
* @property {Function} mount
* @property {Function} update
* @property {Function} unmount
* @property {Object} options
*
* @typedef {Object} DataPoint
* @property {string} label - required
* @property {number} value - required
*/
export default class SimplePie extends Chart {
/**
* @param {Object} props
* @param {DataPoint[]} props.data
* @param {boolean} props.sorted - default false
* @param {Object} props.colorScale - default new Plottable.Scales.Color()
* @param {number} props.innerRadius - default 0
* @param {number} props.outerRadius - default min(plot.height, plot.width) / 2
* @param {Function} props.labelFormatter - optional
* @param {('t'|'r'|'b'|'l'|'none')} props.legendPosition - default 'none'
* @param {boolean} props.animated - default true
* @param {Function} props.clickHandler - optional
* @param {Function} props.hoverHandler - optional
*
* @return {Chart}
*/
constructor (props) {
super()
this.options.legendPosition = 'none'
props = Object.assign(this.options, props)
if (props.sorted) props.data = sortBy(props.data, 'value')
if (props.sorted === 'd') props.data.reverse()
this.dataset = new Plottable.Dataset(props.data)
const total = props.data.reduce((sum, d) => sum + d.value, 0)
const scale = new Plottable.Scales.Linear().domain([0, total])
const colorScale = props.colorScale || new Plottable.Scales.Color()
props.outerRadius = props.outerRadius || (d => Math.min(this.plot.width(), this.plot.height()) / 2)
this.plot = new Plottable.Plots.Pie()
.addClass('simple-pie-plot')
.addDataset(this.dataset)
.sectorValue(d => d.value, scale)
.attr('fill', d => d.label, colorScale)
.labelsEnabled(false)
.innerRadius(props.innerRadius)
.outerRadius(props.outerRadius)
.animated(props.animated)
if (props.labelFormatter) {
this.plot.labelFormatter(props.labelFormatter).labelsEnabled(true)
}
this.layout = this.plot
this._setLegend(props, colorScale)
this._setInteractions(props)
}
update (nextProps) {
if (this.options.sorted) nextProps.data = sortBy(nextProps.data, 'value')
if (this.options.sorted === 'd') nextProps.data.reverse()
const total = nextProps.data.reduce((sum, d) => sum + d.value, 0)
this.plot.sectorValue().scale.domain([0, total])
this.dataset.data(nextProps.data)
Object.assign(this.options, {data: nextProps.data})
this.onUpdate(nextProps)
}
}