1 | import { jsx } from '../../jsx';
|
2 | import Component from '../../base/component';
|
3 | import { partition, hierarchy } from '../../deps/d3-hierarchy/src';
|
4 | import { Category } from '../../attr';
|
5 | import { isInBBox } from '../../util';
|
6 | import CoordController from '../../controller/coord';
|
7 | import { mix, isFunction } from '@antv/util';
|
8 | import Coord from '../../coord';
|
9 | import { Ref } from '../../types';
|
10 |
|
11 | function rootParent(data) {
|
12 | let d = data;
|
13 | while (d.depth > 1) {
|
14 | d = d.parent;
|
15 | }
|
16 | return d;
|
17 | }
|
18 |
|
19 | export default (View) => {
|
20 | return class Sunburst extends Component {
|
21 | coordController: CoordController;
|
22 | coord: Coord;
|
23 | color: Category;
|
24 | triggerRef: Ref[];
|
25 |
|
26 | constructor(props, context) {
|
27 | super(props, context);
|
28 | const { coord, color, data } = props;
|
29 | const { width, height, theme } = context;
|
30 |
|
31 | this.coordController = new CoordController();
|
32 |
|
33 | const { coordController } = this;
|
34 | this.coord = coordController.create(coord, { width, height });
|
35 | this.color = new Category({
|
36 | range: theme.colors,
|
37 | ...color,
|
38 | data,
|
39 | });
|
40 | }
|
41 |
|
42 | didMount() {
|
43 | const { props, container } = this;
|
44 | const { onClick } = props;
|
45 | const canvas = container.get('canvas');
|
46 |
|
47 | this.triggerRef = [];
|
48 |
|
49 | canvas.on('click', (ev) => {
|
50 | const { points } = ev;
|
51 | const shape = this.triggerRef.find((ref) => {
|
52 | return isInBBox(ref.current.getBBox(), points[0]);
|
53 | });
|
54 | if (shape) {
|
55 | ev.shape = shape;
|
56 |
|
57 | ev.payload = shape.payload;
|
58 | onClick && onClick(ev);
|
59 | }
|
60 | });
|
61 | }
|
62 |
|
63 | _mapping(children) {
|
64 | const { color: colorAttr, coord } = this;
|
65 | for (let i = 0, len = children.length; i < len; i++) {
|
66 | const node = children[i];
|
67 | const root = rootParent(node);
|
68 | const color = colorAttr.mapping(root.data[colorAttr.field]);
|
69 | node.color = color;
|
70 | const { x0, x1, y0, y1 } = node;
|
71 | const rect = coord.convertRect({
|
72 | x: [x0, x1],
|
73 | y: [y0, y1],
|
74 | });
|
75 | mix(node, rect);
|
76 |
|
77 | if (node.children && node.children.length) {
|
78 | this._mapping(node.children);
|
79 | }
|
80 | }
|
81 | }
|
82 |
|
83 | sunburst() {
|
84 | const { props } = this;
|
85 | const { data, value, sort = true } = props;
|
86 |
|
87 | const root = hierarchy({ children: data }).sum(function(d) {
|
88 | return d[value];
|
89 | });
|
90 |
|
91 |
|
92 | if (sort === true || isFunction(sort)) {
|
93 | const sortFn = isFunction(sort) ? sort : (a, b) => b[value] - a[value];
|
94 | root.sort(sortFn);
|
95 | }
|
96 |
|
97 | const nodes = partition()(root);
|
98 | const { children } = nodes;
|
99 | this._mapping(children);
|
100 | return nodes;
|
101 | }
|
102 |
|
103 | render() {
|
104 | const node = this.sunburst();
|
105 | const { coord, props } = this;
|
106 | return <View {...props} coord={coord} node={node} triggerRef={this.triggerRef} />;
|
107 | }
|
108 | };
|
109 | };
|