216 lines
6.5 KiB
JavaScript
216 lines
6.5 KiB
JavaScript
|
|
||
|
/*
|
||
|
* 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;
|