2
* Licensed to the Apache Software Foundation (ASF) under one
3
* or more contributor license agreements. See the NOTICE file
4
* distributed with this work for additional information
5
* regarding copyright ownership. The ASF licenses this file
6
* to you under the Apache License, Version 2.0 (the
7
* "License"); you may not use this file except in compliance
8
* with the License. You may obtain a copy of the License at
10
* http://www.apache.org/licenses/LICENSE-2.0
12
* Unless required by applicable law or agreed to in writing,
13
* software distributed under the License is distributed on an
14
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
* KIND, either express or implied. See the License for the
16
* specific language governing permissions and limitations
20
import * as zrUtil from 'zrender/src/core/util';
21
import SeriesModel from '../../model/Series';
22
import Tree, { TreeNode } from '../../data/Tree';
23
import {wrapTreePathInfo} from '../helper/treeHelper';
26
CircleLayoutOptionMixin,
35
} from '../../util/types';
36
import GlobalModel from '../../model/Global';
37
import SeriesData from '../../data/SeriesData';
38
import Model from '../../model/Model';
39
import enableAriaDecalForTree from '../helper/enableAriaDecalForTree';
41
interface SunburstItemStyleOption<TCbParams = never> extends ItemStyleOption<TCbParams> {
43
// which means that both innerCornerRadius and outerCornerRadius are 10
44
// can also be an array [20, 10]
45
// which means that innerCornerRadius is 20
46
// and outerCornerRadius is 10
47
// can also be a string or string array, such as ['20%', '50%']
48
// which means that innerCornerRadius is 20% of the innerRadius
49
// and outerCornerRadius is half of outerRadius.
50
borderRadius?: (number | string)[] | number | string
53
interface SunburstLabelOption extends Omit<SeriesLabelOption<SunburstDataParams>, 'rotate' | 'position'> {
54
rotate?: 'radial' | 'tangential' | number
57
position?: SeriesLabelOption['position'] | 'outside'
60
interface SunburstDataParams extends CallbackDataParams {
64
value: SunburstSeriesNodeItemOption['value']
68
interface SunburstStatesMixin {
70
focus?: DefaultEmphasisFocus | 'descendant' | 'ancestor'
74
export interface SunburstStateOption<TCbParams = never> {
75
itemStyle?: SunburstItemStyleOption<TCbParams>
76
label?: SunburstLabelOption
79
export interface SunburstSeriesNodeItemOption extends
80
SunburstStateOption<SunburstDataParams>,
81
StatesOptionMixin<SunburstStateOption<SunburstDataParams>, SunburstStatesMixin>,
82
OptionDataItemObject<OptionDataValue>
84
nodeClick?: 'rootToNode' | 'link' | false
85
// Available when nodeClick is link
89
children?: SunburstSeriesNodeItemOption[]
95
export interface SunburstSeriesLevelOption extends
96
SunburstStateOption<SunburstDataParams>,
97
StatesOptionMixin<SunburstStateOption<SunburstDataParams>, SunburstStatesMixin> {
99
radius?: (number | string)[]
101
* @deprecated use radius instead
105
* @deprecated use radius instead
110
itemStyle?: SunburstItemStyleOption
111
label?: SunburstLabelOption
115
interface SortParam {
121
export interface SunburstSeriesOption extends
122
SeriesOption<SunburstStateOption<SunburstDataParams>, SunburstStatesMixin>,
123
SunburstStateOption<SunburstDataParams>,
124
SunburstColorByMixin,
125
CircleLayoutOptionMixin {
133
* If still show when all data zero.
135
stillShowZeroSum?: boolean
137
* Policy of highlighting pieces when hover on one
138
* Valid values: 'none' (for not downplay others), 'descendant',
141
// highlightPolicy?: 'descendant' | 'ancestor' | 'self'
143
nodeClick?: 'rootToNode' | 'link' | false
145
renderLabelForZeroData?: boolean
147
data?: SunburstSeriesNodeItemOption[]
149
levels?: SunburstSeriesLevelOption[]
151
animationType?: 'expansion' | 'scale'
153
sort?: 'desc' | 'asc' | ((a: SortParam, b: SortParam) => number)
156
interface SunburstSeriesModel {
159
state?: 'emphasis' | 'normal' | 'highlight' | 'blur' | 'select'
162
class SunburstSeriesModel extends SeriesModel<SunburstSeriesOption> {
164
static readonly type = 'series.sunburst';
165
readonly type = SunburstSeriesModel.type;
167
ignoreStyleOnData = true;
169
private _viewRoot: TreeNode;
170
private _levelModels: Model<SunburstSeriesLevelOption>[];
172
getInitialData(option: SunburstSeriesOption, ecModel: GlobalModel) {
173
// Create a virtual root.
174
const root = { name: option.name, children: option.data } as SunburstSeriesNodeItemOption;
176
completeTreeValue(root);
178
const levelModels = this._levelModels =
179
zrUtil.map(option.levels || [], function (levelDefine) {
180
return new Model(levelDefine, this, ecModel);
183
// Make sure always a new tree is created when setOption,
184
// in TreemapView, we check whether oldTree === newTree
185
// to choose mappings approach among old shapes and new shapes.
186
const tree = Tree.createTree(root, this, beforeLink);
188
function beforeLink(nodeData: SeriesData) {
189
nodeData.wrapMethod('getItemModel', function (model, idx) {
190
const node = tree.getNodeByDataIndex(idx);
191
const levelModel = levelModels[node.depth];
192
levelModel && (model.parentModel = levelModel);
200
this.resetViewRoot();
206
getDataParams(dataIndex: number) {
207
const params = super.getDataParams.apply(this, arguments as any) as SunburstDataParams;
209
const node = this.getData().tree.getNodeByDataIndex(dataIndex);
210
params.treePathInfo = wrapTreePathInfo<SunburstSeriesNodeItemOption['value']>(node, this);
215
getLevelModel(node: TreeNode) {
216
return this._levelModels && this._levelModels[node.depth];
219
static defaultOption: SunburstSeriesOption = {
224
center: ['50%', '50%'],
232
// If still show when all data zero.
233
stillShowZeroSum: true,
235
// 'rootToNode', 'link', or false
236
nodeClick: 'rootToNode',
238
renderLabelForZeroData: false,
241
// could be: 'radial', 'tangential', or 'none'
245
// 'left' is for inner side of inside, and 'right' is for outer
254
borderColor: 'white',
257
shadowColor: 'rgba(0, 0, 0, 0.2)',
276
// Animation type can be expansion, scale.
277
animationType: 'expansion',
278
animationDuration: 1000,
279
animationDurationUpdate: 500,
286
* Valid values: 'desc', 'asc', null, or callback function.
287
* 'desc' and 'asc' for descend and ascendant order;
288
* null for not sorting;
289
* example of callback function:
290
* function(nodeA, nodeB) {
291
* return nodeA.getValue() - nodeB.getValue();
298
return this._viewRoot;
301
resetViewRoot(viewRoot?: TreeNode) {
303
? (this._viewRoot = viewRoot)
304
: (viewRoot = this._viewRoot);
306
const root = this.getRawData().tree.root;
309
|| (viewRoot !== root && !root.contains(viewRoot))
311
this._viewRoot = root;
316
enableAriaDecalForTree(this);
322
function completeTreeValue(dataNode: SunburstSeriesNodeItemOption) {
323
// Postorder travel tree.
324
// If value of none-leaf node is not set,
325
// calculate it by suming up the value of all children.
328
zrUtil.each(dataNode.children, function (child) {
330
completeTreeValue(child);
332
let childValue = child.value;
333
// TODO First value of array must be a number
334
zrUtil.isArray(childValue) && (childValue = childValue[0]);
335
sum += childValue as number;
338
let thisValue = dataNode.value as number;
339
if (zrUtil.isArray(thisValue)) {
340
thisValue = thisValue[0];
343
if (thisValue == null || isNaN(thisValue)) {
346
// Value should not less than 0.
351
zrUtil.isArray(dataNode.value)
352
? (dataNode.value[0] = thisValue)
353
: (dataNode.value = thisValue);
357
export default SunburstSeriesModel;