first commit

This commit is contained in:
jefferyzhao
2025-07-31 17:44:12 +08:00
commit b9bdc8598b
42390 changed files with 4467935 additions and 0 deletions

View File

@ -0,0 +1,395 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var zrUtil = require("zrender/lib/core/util");
var graphic = require("../../util/graphic");
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var NodeHighlightPolicy = {
NONE: 'none',
// not downplay others
DESCENDANT: 'descendant',
ANCESTOR: 'ancestor',
SELF: 'self'
};
var DEFAULT_SECTOR_Z = 2;
var DEFAULT_TEXT_Z = 4;
/**
* Sunburstce of Sunburst including Sector, Label, LabelLine
* @constructor
* @extends {module:zrender/graphic/Group}
*/
function SunburstPiece(node, seriesModel, ecModel) {
graphic.Group.call(this);
var sector = new graphic.Sector({
z2: DEFAULT_SECTOR_Z
});
sector.seriesIndex = seriesModel.seriesIndex;
var text = new graphic.Text({
z2: DEFAULT_TEXT_Z,
silent: node.getModel('label').get('silent')
});
this.add(sector);
this.add(text);
this.updateData(true, node, 'normal', seriesModel, ecModel); // Hover to change label and labelLine
function onEmphasis() {
text.ignore = text.hoverIgnore;
}
function onNormal() {
text.ignore = text.normalIgnore;
}
this.on('emphasis', onEmphasis).on('normal', onNormal).on('mouseover', onEmphasis).on('mouseout', onNormal);
}
var SunburstPieceProto = SunburstPiece.prototype;
SunburstPieceProto.updateData = function (firstCreate, node, state, seriesModel, ecModel) {
this.node = node;
node.piece = this;
seriesModel = seriesModel || this._seriesModel;
ecModel = ecModel || this._ecModel;
var sector = this.childAt(0);
sector.dataIndex = node.dataIndex;
var itemModel = node.getModel();
var layout = node.getLayout(); // if (!layout) {
// console.log(node.getLayout());
// }
var sectorShape = zrUtil.extend({}, layout);
sectorShape.label = null;
var visualColor = getNodeColor(node, seriesModel, ecModel);
fillDefaultColor(node, seriesModel, visualColor);
var normalStyle = itemModel.getModel('itemStyle').getItemStyle();
var style;
if (state === 'normal') {
style = normalStyle;
} else {
var stateStyle = itemModel.getModel(state + '.itemStyle').getItemStyle();
style = zrUtil.merge(stateStyle, normalStyle);
}
style = zrUtil.defaults({
lineJoin: 'bevel',
fill: style.fill || visualColor
}, style);
if (firstCreate) {
sector.setShape(sectorShape);
sector.shape.r = layout.r0;
graphic.updateProps(sector, {
shape: {
r: layout.r
}
}, seriesModel, node.dataIndex);
sector.useStyle(style);
} else if (typeof style.fill === 'object' && style.fill.type || typeof sector.style.fill === 'object' && sector.style.fill.type) {
// Disable animation for gradient since no interpolation method
// is supported for gradient
graphic.updateProps(sector, {
shape: sectorShape
}, seriesModel);
sector.useStyle(style);
} else {
graphic.updateProps(sector, {
shape: sectorShape,
style: style
}, seriesModel);
}
this._updateLabel(seriesModel, visualColor, state);
var cursorStyle = itemModel.getShallow('cursor');
cursorStyle && sector.attr('cursor', cursorStyle);
if (firstCreate) {
var highlightPolicy = seriesModel.getShallow('highlightPolicy');
this._initEvents(sector, node, seriesModel, highlightPolicy);
}
this._seriesModel = seriesModel || this._seriesModel;
this._ecModel = ecModel || this._ecModel;
graphic.setHoverStyle(this);
};
SunburstPieceProto.onEmphasis = function (highlightPolicy) {
var that = this;
this.node.hostTree.root.eachNode(function (n) {
if (n.piece) {
if (that.node === n) {
n.piece.updateData(false, n, 'emphasis');
} else if (isNodeHighlighted(n, that.node, highlightPolicy)) {
n.piece.childAt(0).trigger('highlight');
} else if (highlightPolicy !== NodeHighlightPolicy.NONE) {
n.piece.childAt(0).trigger('downplay');
}
}
});
};
SunburstPieceProto.onNormal = function () {
this.node.hostTree.root.eachNode(function (n) {
if (n.piece) {
n.piece.updateData(false, n, 'normal');
}
});
};
SunburstPieceProto.onHighlight = function () {
this.updateData(false, this.node, 'highlight');
};
SunburstPieceProto.onDownplay = function () {
this.updateData(false, this.node, 'downplay');
};
SunburstPieceProto._updateLabel = function (seriesModel, visualColor, state) {
var itemModel = this.node.getModel();
var normalModel = itemModel.getModel('label');
var labelModel = state === 'normal' || state === 'emphasis' ? normalModel : itemModel.getModel(state + '.label');
var labelHoverModel = itemModel.getModel('emphasis.label');
var labelFormatter = labelModel.get('formatter'); // Use normal formatter if no state formatter is defined
var labelState = labelFormatter ? state : 'normal';
var text = zrUtil.retrieve(seriesModel.getFormattedLabel(this.node.dataIndex, labelState, null, null, 'label'), this.node.name);
if (getLabelAttr('show') === false) {
text = '';
}
var layout = this.node.getLayout();
var labelMinAngle = labelModel.get('minAngle');
if (labelMinAngle == null) {
labelMinAngle = normalModel.get('minAngle');
}
labelMinAngle = labelMinAngle / 180 * Math.PI;
var angle = layout.endAngle - layout.startAngle;
if (labelMinAngle != null && Math.abs(angle) < labelMinAngle) {
// Not displaying text when angle is too small
text = '';
}
var label = this.childAt(1);
graphic.setLabelStyle(label.style, label.hoverStyle || {}, normalModel, labelHoverModel, {
defaultText: labelModel.getShallow('show') ? text : null,
autoColor: visualColor,
useInsideStyle: true
});
var midAngle = (layout.startAngle + layout.endAngle) / 2;
var dx = Math.cos(midAngle);
var dy = Math.sin(midAngle);
var r;
var labelPosition = getLabelAttr('position');
var labelPadding = getLabelAttr('distance') || 0;
var textAlign = getLabelAttr('align');
if (labelPosition === 'outside') {
r = layout.r + labelPadding;
textAlign = midAngle > Math.PI / 2 ? 'right' : 'left';
} else {
if (!textAlign || textAlign === 'center') {
r = (layout.r + layout.r0) / 2;
textAlign = 'center';
} else if (textAlign === 'left') {
r = layout.r0 + labelPadding;
if (midAngle > Math.PI / 2) {
textAlign = 'right';
}
} else if (textAlign === 'right') {
r = layout.r - labelPadding;
if (midAngle > Math.PI / 2) {
textAlign = 'left';
}
}
}
label.attr('style', {
text: text,
textAlign: textAlign,
textVerticalAlign: getLabelAttr('verticalAlign') || 'middle',
opacity: getLabelAttr('opacity')
});
var textX = r * dx + layout.cx;
var textY = r * dy + layout.cy;
label.attr('position', [textX, textY]);
var rotateType = getLabelAttr('rotate');
var rotate = 0;
if (rotateType === 'radial') {
rotate = -midAngle;
if (rotate < -Math.PI / 2) {
rotate += Math.PI;
}
} else if (rotateType === 'tangential') {
rotate = Math.PI / 2 - midAngle;
if (rotate > Math.PI / 2) {
rotate -= Math.PI;
} else if (rotate < -Math.PI / 2) {
rotate += Math.PI;
}
} else if (typeof rotateType === 'number') {
rotate = rotateType * Math.PI / 180;
}
label.attr('rotation', rotate);
function getLabelAttr(name) {
var stateAttr = labelModel.get(name);
if (stateAttr == null) {
return normalModel.get(name);
} else {
return stateAttr;
}
}
};
SunburstPieceProto._initEvents = function (sector, node, seriesModel, highlightPolicy) {
sector.off('mouseover').off('mouseout').off('emphasis').off('normal');
var that = this;
var onEmphasis = function () {
that.onEmphasis(highlightPolicy);
};
var onNormal = function () {
that.onNormal();
};
var onDownplay = function () {
that.onDownplay();
};
var onHighlight = function () {
that.onHighlight();
};
if (seriesModel.isAnimationEnabled()) {
sector.on('mouseover', onEmphasis).on('mouseout', onNormal).on('emphasis', onEmphasis).on('normal', onNormal).on('downplay', onDownplay).on('highlight', onHighlight);
}
};
zrUtil.inherits(SunburstPiece, graphic.Group);
var _default = SunburstPiece;
/**
* Get node color
*
* @param {TreeNode} node the node to get color
* @param {module:echarts/model/Series} seriesModel series
* @param {module:echarts/model/Global} ecModel echarts defaults
*/
function getNodeColor(node, seriesModel, ecModel) {
// Color from visualMap
var visualColor = node.getVisual('color');
var visualMetaList = node.getVisual('visualMeta');
if (!visualMetaList || visualMetaList.length === 0) {
// Use first-generation color if has no visualMap
visualColor = null;
} // Self color or level color
var color = node.getModel('itemStyle').get('color');
if (color) {
return color;
} else if (visualColor) {
// Color mapping
return visualColor;
} else if (node.depth === 0) {
// Virtual root node
return ecModel.option.color[0];
} else {
// First-generation color
var length = ecModel.option.color.length;
color = ecModel.option.color[getRootId(node) % length];
}
return color;
}
/**
* Get index of root in sorted order
*
* @param {TreeNode} node current node
* @return {number} index in root
*/
function getRootId(node) {
var ancestor = node;
while (ancestor.depth > 1) {
ancestor = ancestor.parentNode;
}
var virtualRoot = node.getAncestors()[0];
return zrUtil.indexOf(virtualRoot.children, ancestor);
}
function isNodeHighlighted(node, activeNode, policy) {
if (policy === NodeHighlightPolicy.NONE) {
return false;
} else if (policy === NodeHighlightPolicy.SELF) {
return node === activeNode;
} else if (policy === NodeHighlightPolicy.ANCESTOR) {
return node === activeNode || node.isAncestorOf(activeNode);
} else {
return node === activeNode || node.isDescendantOf(activeNode);
}
} // Fix tooltip callback function params.color incorrect when pick a default color
function fillDefaultColor(node, seriesModel, color) {
var data = seriesModel.getData();
data.setItemVisual(node.dataIndex, 'color', color);
}
module.exports = _default;

View File

@ -0,0 +1,224 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var zrUtil = require("zrender/lib/core/util");
var SeriesModel = require("../../model/Series");
var Tree = require("../../data/Tree");
var Model = require("../../model/Model");
var _treeHelper = require("../helper/treeHelper");
var wrapTreePathInfo = _treeHelper.wrapTreePathInfo;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var _default = SeriesModel.extend({
type: 'series.sunburst',
/**
* @type {module:echarts/data/Tree~Node}
*/
_viewRoot: null,
getInitialData: function (option, ecModel) {
// Create a virtual root.
var root = {
name: option.name,
children: option.data
};
completeTreeValue(root);
var levelModels = zrUtil.map(option.levels || [], function (levelDefine) {
return new Model(levelDefine, this, ecModel);
}, this); // Make sure always a new tree is created when setOption,
// in TreemapView, we check whether oldTree === newTree
// to choose mappings approach among old shapes and new shapes.
var tree = Tree.createTree(root, this, beforeLink);
function beforeLink(nodeData) {
nodeData.wrapMethod('getItemModel', function (model, idx) {
var node = tree.getNodeByDataIndex(idx);
var levelModel = levelModels[node.depth];
levelModel && (model.parentModel = levelModel);
return model;
});
}
return tree.data;
},
optionUpdated: function () {
this.resetViewRoot();
},
/*
* @override
*/
getDataParams: function (dataIndex) {
var params = SeriesModel.prototype.getDataParams.apply(this, arguments);
var node = this.getData().tree.getNodeByDataIndex(dataIndex);
params.treePathInfo = wrapTreePathInfo(node, this);
return params;
},
defaultOption: {
zlevel: 0,
z: 2,
// 默认全局居中
center: ['50%', '50%'],
radius: [0, '75%'],
// 默认顺时针
clockwise: true,
startAngle: 90,
// 最小角度改为0
minAngle: 0,
percentPrecision: 2,
// If still show when all data zero.
stillShowZeroSum: true,
// Policy of highlighting pieces when hover on one
// Valid values: 'none' (for not downplay others), 'descendant',
// 'ancestor', 'self'
highlightPolicy: 'descendant',
// 'rootToNode', 'link', or false
nodeClick: 'rootToNode',
renderLabelForZeroData: false,
label: {
// could be: 'radial', 'tangential', or 'none'
rotate: 'radial',
show: true,
opacity: 1,
// 'left' is for inner side of inside, and 'right' is for outter
// side for inside
align: 'center',
position: 'inside',
distance: 5,
silent: true
},
itemStyle: {
borderWidth: 1,
borderColor: 'white',
borderType: 'solid',
shadowBlur: 0,
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowOffsetX: 0,
shadowOffsetY: 0,
opacity: 1
},
highlight: {
itemStyle: {
opacity: 1
}
},
downplay: {
itemStyle: {
opacity: 0.5
},
label: {
opacity: 0.6
}
},
// Animation type canbe expansion, scale
animationType: 'expansion',
animationDuration: 1000,
animationDurationUpdate: 500,
animationEasing: 'cubicOut',
data: [],
levels: [],
/**
* Sort order.
*
* Valid values: 'desc', 'asc', null, or callback function.
* 'desc' and 'asc' for descend and ascendant order;
* null for not sorting;
* example of callback function:
* function(nodeA, nodeB) {
* return nodeA.getValue() - nodeB.getValue();
* }
*/
sort: 'desc'
},
getViewRoot: function () {
return this._viewRoot;
},
/**
* @param {module:echarts/data/Tree~Node} [viewRoot]
*/
resetViewRoot: function (viewRoot) {
viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot;
var root = this.getRawData().tree.root;
if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) {
this._viewRoot = root;
}
}
});
/**
* @param {Object} dataNode
*/
function completeTreeValue(dataNode) {
// Postorder travel tree.
// If value of none-leaf node is not set,
// calculate it by suming up the value of all children.
var sum = 0;
zrUtil.each(dataNode.children, function (child) {
completeTreeValue(child);
var childValue = child.value;
zrUtil.isArray(childValue) && (childValue = childValue[0]);
sum += childValue;
});
var thisValue = dataNode.value;
if (zrUtil.isArray(thisValue)) {
thisValue = thisValue[0];
}
if (thisValue == null || isNaN(thisValue)) {
thisValue = sum;
} // Value should not less than 0.
if (thisValue < 0) {
thisValue = 0;
}
zrUtil.isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue;
}
module.exports = _default;

247
node_modules/echarts/lib/chart/sunburst/SunburstView.js generated vendored Normal file
View File

@ -0,0 +1,247 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var zrUtil = require("zrender/lib/core/util");
var ChartView = require("../../view/Chart");
var SunburstPiece = require("./SunburstPiece");
var DataDiffer = require("../../data/DataDiffer");
var _format = require("../../util/format");
var windowOpen = _format.windowOpen;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var ROOT_TO_NODE_ACTION = 'sunburstRootToNode';
var SunburstView = ChartView.extend({
type: 'sunburst',
init: function () {},
render: function (seriesModel, ecModel, api, payload) {
var that = this;
this.seriesModel = seriesModel;
this.api = api;
this.ecModel = ecModel;
var data = seriesModel.getData();
var virtualRoot = data.tree.root;
var newRoot = seriesModel.getViewRoot();
var group = this.group;
var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData');
var newChildren = [];
newRoot.eachNode(function (node) {
newChildren.push(node);
});
var oldChildren = this._oldChildren || [];
dualTravel(newChildren, oldChildren);
renderRollUp(virtualRoot, newRoot);
if (payload && payload.highlight && payload.highlight.piece) {
var highlightPolicy = seriesModel.getShallow('highlightPolicy');
payload.highlight.piece.onEmphasis(highlightPolicy);
} else if (payload && payload.unhighlight) {
var piece = this.virtualPiece;
if (!piece && virtualRoot.children.length) {
piece = virtualRoot.children[0].piece;
}
if (piece) {
piece.onNormal();
}
}
this._initEvents();
this._oldChildren = newChildren;
function dualTravel(newChildren, oldChildren) {
if (newChildren.length === 0 && oldChildren.length === 0) {
return;
}
new DataDiffer(oldChildren, newChildren, getKey, getKey).add(processNode).update(processNode).remove(zrUtil.curry(processNode, null)).execute();
function getKey(node) {
return node.getId();
}
function processNode(newId, oldId) {
var newNode = newId == null ? null : newChildren[newId];
var oldNode = oldId == null ? null : oldChildren[oldId];
doRenderNode(newNode, oldNode);
}
}
function doRenderNode(newNode, oldNode) {
if (!renderLabelForZeroData && newNode && !newNode.getValue()) {
// Not render data with value 0
newNode = null;
}
if (newNode !== virtualRoot && oldNode !== virtualRoot) {
if (oldNode && oldNode.piece) {
if (newNode) {
// Update
oldNode.piece.updateData(false, newNode, 'normal', seriesModel, ecModel); // For tooltip
data.setItemGraphicEl(newNode.dataIndex, oldNode.piece);
} else {
// Remove
removeNode(oldNode);
}
} else if (newNode) {
// Add
var piece = new SunburstPiece(newNode, seriesModel, ecModel);
group.add(piece); // For tooltip
data.setItemGraphicEl(newNode.dataIndex, piece);
}
}
}
function removeNode(node) {
if (!node) {
return;
}
if (node.piece) {
group.remove(node.piece);
node.piece = null;
}
}
function renderRollUp(virtualRoot, viewRoot) {
if (viewRoot.depth > 0) {
// Render
if (that.virtualPiece) {
// Update
that.virtualPiece.updateData(false, virtualRoot, 'normal', seriesModel, ecModel);
} else {
// Add
that.virtualPiece = new SunburstPiece(virtualRoot, seriesModel, ecModel);
group.add(that.virtualPiece);
}
if (viewRoot.piece._onclickEvent) {
viewRoot.piece.off('click', viewRoot.piece._onclickEvent);
}
var event = function (e) {
that._rootToNode(viewRoot.parentNode);
};
viewRoot.piece._onclickEvent = event;
that.virtualPiece.on('click', event);
} else if (that.virtualPiece) {
// Remove
group.remove(that.virtualPiece);
that.virtualPiece = null;
}
}
},
dispose: function () {},
/**
* @private
*/
_initEvents: function () {
var that = this;
var event = function (e) {
var targetFound = false;
var viewRoot = that.seriesModel.getViewRoot();
viewRoot.eachNode(function (node) {
if (!targetFound && node.piece && node.piece.childAt(0) === e.target) {
var nodeClick = node.getModel().get('nodeClick');
if (nodeClick === 'rootToNode') {
that._rootToNode(node);
} else if (nodeClick === 'link') {
var itemModel = node.getModel();
var link = itemModel.get('link');
if (link) {
var linkTarget = itemModel.get('target', true) || '_blank';
windowOpen(link, linkTarget);
}
}
targetFound = true;
}
});
};
if (this.group._onclickEvent) {
this.group.off('click', this.group._onclickEvent);
}
this.group.on('click', event);
this.group._onclickEvent = event;
},
/**
* @private
*/
_rootToNode: function (node) {
if (node !== this.seriesModel.getViewRoot()) {
this.api.dispatchAction({
type: ROOT_TO_NODE_ACTION,
from: this.uid,
seriesId: this.seriesModel.id,
targetNode: node
});
}
},
/**
* @implement
*/
containPoint: function (point, seriesModel) {
var treeRoot = seriesModel.getData();
var itemLayout = treeRoot.getItemLayout(0);
if (itemLayout) {
var dx = point[0] - itemLayout.cx;
var dy = point[1] - itemLayout.cy;
var radius = Math.sqrt(dx * dx + dy * dy);
return radius <= itemLayout.r && radius >= itemLayout.r0;
}
}
});
var _default = SunburstView;
module.exports = _default;

View File

@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var echarts = require("../../echarts");
var helper = require("../helper/treeHelper");
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @file Sunburst action
*/
var ROOT_TO_NODE_ACTION = 'sunburstRootToNode';
echarts.registerAction({
type: ROOT_TO_NODE_ACTION,
update: 'updateView'
}, function (payload, ecModel) {
ecModel.eachComponent({
mainType: 'series',
subType: 'sunburst',
query: payload
}, handleRootToNode);
function handleRootToNode(model, index) {
var targetInfo = helper.retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION], model);
if (targetInfo) {
var originViewRoot = model.getViewRoot();
if (originViewRoot) {
payload.direction = helper.aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown';
}
model.resetViewRoot(targetInfo.node);
}
}
});
var HIGHLIGHT_ACTION = 'sunburstHighlight';
echarts.registerAction({
type: HIGHLIGHT_ACTION,
update: 'updateView'
}, function (payload, ecModel) {
ecModel.eachComponent({
mainType: 'series',
subType: 'sunburst',
query: payload
}, handleHighlight);
function handleHighlight(model, index) {
var targetInfo = helper.retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model);
if (targetInfo) {
payload.highlight = targetInfo.node;
}
}
});
var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight';
echarts.registerAction({
type: UNHIGHLIGHT_ACTION,
update: 'updateView'
}, function (payload, ecModel) {
ecModel.eachComponent({
mainType: 'series',
subType: 'sunburst',
query: payload
}, handleUnhighlight);
function handleUnhighlight(model, index) {
payload.unhighlight = true;
}
});

View File

@ -0,0 +1,216 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var _number = require("../../util/number");
var parsePercent = _number.parsePercent;
var zrUtil = require("zrender/lib/core/util");
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// var PI2 = Math.PI * 2;
var RADIAN = Math.PI / 180;
function _default(seriesType, ecModel, api, payload) {
ecModel.eachSeriesByType(seriesType, function (seriesModel) {
var center = seriesModel.get('center');
var radius = seriesModel.get('radius');
if (!zrUtil.isArray(radius)) {
radius = [0, radius];
}
if (!zrUtil.isArray(center)) {
center = [center, center];
}
var width = api.getWidth();
var height = api.getHeight();
var size = Math.min(width, height);
var cx = parsePercent(center[0], width);
var cy = parsePercent(center[1], height);
var r0 = parsePercent(radius[0], size / 2);
var r = parsePercent(radius[1], size / 2);
var startAngle = -seriesModel.get('startAngle') * RADIAN;
var minAngle = seriesModel.get('minAngle') * RADIAN;
var virtualRoot = seriesModel.getData().tree.root;
var treeRoot = seriesModel.getViewRoot();
var rootDepth = treeRoot.depth;
var sort = seriesModel.get('sort');
if (sort != null) {
initChildren(treeRoot, sort);
}
var validDataCount = 0;
zrUtil.each(treeRoot.children, function (child) {
!isNaN(child.getValue()) && validDataCount++;
});
var sum = treeRoot.getValue(); // Sum may be 0
var unitRadian = Math.PI / (sum || validDataCount) * 2;
var renderRollupNode = treeRoot.depth > 0;
var levels = treeRoot.height - (renderRollupNode ? -1 : 1);
var rPerLevel = (r - r0) / (levels || 1);
var clockwise = seriesModel.get('clockwise');
var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); // In the case some sector angle is smaller than minAngle
// var restAngle = PI2;
// var valueSumLargerThanMinAngle = 0;
var dir = clockwise ? 1 : -1;
/**
* Render a tree
* @return increased angle
*/
var renderNode = function (node, startAngle) {
if (!node) {
return;
}
var endAngle = startAngle; // Render self
if (node !== virtualRoot) {
// Tree node is virtual, so it doesn't need to be drawn
var value = node.getValue();
var angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian;
if (angle < minAngle) {
angle = minAngle; // restAngle -= minAngle;
} // else {
// valueSumLargerThanMinAngle += value;
// }
endAngle = startAngle + dir * angle;
var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1);
var rStart = r0 + rPerLevel * depth;
var rEnd = r0 + rPerLevel * (depth + 1);
var itemModel = node.getModel();
if (itemModel.get('r0') != null) {
rStart = parsePercent(itemModel.get('r0'), size / 2);
}
if (itemModel.get('r') != null) {
rEnd = parsePercent(itemModel.get('r'), size / 2);
}
node.setLayout({
angle: angle,
startAngle: startAngle,
endAngle: endAngle,
clockwise: clockwise,
cx: cx,
cy: cy,
r0: rStart,
r: rEnd
});
} // Render children
if (node.children && node.children.length) {
// currentAngle = startAngle;
var siblingAngle = 0;
zrUtil.each(node.children, function (node) {
siblingAngle += renderNode(node, startAngle + siblingAngle);
});
}
return endAngle - startAngle;
}; // Virtual root node for roll up
if (renderRollupNode) {
var rStart = r0;
var rEnd = r0 + rPerLevel;
var angle = Math.PI * 2;
virtualRoot.setLayout({
angle: angle,
startAngle: startAngle,
endAngle: startAngle + angle,
clockwise: clockwise,
cx: cx,
cy: cy,
r0: rStart,
r: rEnd
});
}
renderNode(treeRoot, startAngle);
});
}
/**
* Init node children by order and update visual
*
* @param {TreeNode} node root node
* @param {boolean} isAsc if is in ascendant order
*/
function initChildren(node, isAsc) {
var children = node.children || [];
node.children = sort(children, isAsc); // Init children recursively
if (children.length) {
zrUtil.each(node.children, function (child) {
initChildren(child, isAsc);
});
}
}
/**
* Sort children nodes
*
* @param {TreeNode[]} children children of node to be sorted
* @param {string | function | null} sort sort method
* See SunburstSeries.js for details.
*/
function sort(children, sortOrder) {
if (typeof sortOrder === 'function') {
return children.sort(sortOrder);
} else {
var isAsc = sortOrder === 'asc';
return children.sort(function (a, b) {
var diff = (a.getValue() - b.getValue()) * (isAsc ? 1 : -1);
return diff === 0 ? (a.dataIndex - b.dataIndex) * (isAsc ? -1 : 1) : diff;
});
}
}
module.exports = _default;