天津投入产出系统后端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1094 lines
41 KiB

/**
* echarts图表类:chord diagram
*
* @author pissang (https://github.com/pissang/)
*
* TODO 非Ribbon Type 支持 undirected graph ?
*/
define(function (require) {
'use strict';
var ChartBase = require('./base');
// 图形依赖
var TextShape = require('zrender/shape/Text');
var LineShape = require('zrender/shape/Line');
var SectorShape = require('zrender/shape/Sector');
var RibbonShape = require('../util/shape/Ribbon');
var IconShape = require('../util/shape/Icon');
var BezierCurveShape = require('zrender/shape/BezierCurve');
var ecConfig = require('../config');
// 和弦图默认参数
ecConfig.chord = {
zlevel: 0, // 一级层叠
z: 2, // 二级层叠
clickable: true,
radius: ['65%', '75%'],
center: ['50%', '50%'],
padding: 2,
sort: 'none', // can be 'none', 'ascending', 'descending'
sortSub: 'none', // can be 'none', 'ascending', 'descending'
startAngle: 90,
clockWise: true,
ribbonType: true,
/***************** 下面的配置项在 ribbonType 为 false 时有效 */
// 同force类似
minRadius: 10,
maxRadius: 20,
symbol: 'circle',
/***************** 上面的配置项在 ribbonType 为 false 时有效 */
/***************** 下面的配置项在 ribbonType 为 true 时有效 */
showScale: false,
showScaleText: false,
/***************** 上面的配置项在 ribbonType 为 true 时有效 */
// 分类里如果有样式会覆盖节点默认样式
// categories: [{
// itemStyle
// symbol
// symbolSize
// name
// }],
itemStyle: {
normal: {
borderWidth: 0,
borderColor: '#000',
label: {
show: true,
rotate: false,
distance: 5
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
},
chordStyle: {
/** ribbonType = false 时有效 */
width: 1,
color: 'black',
/** ribbonType = true 时有效 */
borderWidth: 1,
borderColor: '#999',
opacity: 0.5
}
},
emphasis: {
borderWidth: 0,
borderColor: '#000',
chordStyle: {
/** ribbonType = false 时有效 */
width: 1,
color: 'black',
/** ribbonType = true 时有效 */
borderWidth: 1,
borderColor: '#999'
}
}
}
/****** 使用 Data-matrix 表示数据 */
// data: [],
// Source data matrix
/**
* target
* -1--2--3--4--5-
* 1| x x x x x
* 2| x x x x x
* 3| x x x x x source
* 4| x x x x x
* 5| x x x x x
*
* Relation ship from source to target
* https://github.com/mbostock/d3/wiki/Chord-Layout#wiki-chord
*
* Row based
*/
// matrix: [],
/****** 使用 node-links 表示数据 */
// 参考 force
// nodes: [],
// links: []
};
var ecData = require('../util/ecData');
var zrUtil = require('zrender/tool/util');
var vec2 = require('zrender/tool/vector');
var Graph = require('../data/Graph');
var ChordLayout = require('../layout/Chord');
function Chord(ecTheme, messageCenter, zr, option, myChart) {
// 图表基类
ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
this.scaleLineLength = 4;
this.scaleUnitAngle = 4;
this.refresh(option);
}
Chord.prototype = {
type: ecConfig.CHART_TYPE_CHORD,
/**
* 绘制图形
*/
_init: function () {
var series = this.series;
this.selectedMap = {};
var chordSeriesMap = {};
var chordSeriesGroups = {};
for (var i = 0, l = series.length; i < l; i++) {
if (series[i].type === this.type) {
var _isSelected = this.isSelected(series[i].name);
// Filter by selected serie
this.selectedMap[series[i].name] = _isSelected;
if (_isSelected) {
this.buildMark(i);
}
this.reformOption(series[i]);
chordSeriesMap[series[i].name] = series[i];
}
}
for (var i = 0, l = series.length; i < l; i++) {
if (series[i].type === this.type) {
if (series[i].insertToSerie) {
var referenceSerie = chordSeriesMap[series[i].insertToSerie];
series[i]._referenceSerie = referenceSerie;
}
else {
chordSeriesGroups[series[i].name] = [series[i]];
}
}
}
for (var i = 0, l = series.length; i < l; i++) {
if (series[i].type === this.type) {
if (series[i].insertToSerie) {
// insertToSerie 可能会存在链式的使用,找到最原始的系列,分到一个 Group 里
var mainSerie = series[i]._referenceSerie;
while (mainSerie && mainSerie._referenceSerie) {
mainSerie = mainSerie._referenceSerie;
}
if (
chordSeriesGroups[mainSerie.name]
&& this.selectedMap[series[i].name]
) {
chordSeriesGroups[mainSerie.name].push(series[i]);
}
}
}
}
for (var name in chordSeriesGroups) {
this._buildChords(chordSeriesGroups[name]);
}
this.addShapeList();
},
_getNodeCategory: function (serie, group) {
return serie.categories && serie.categories[group.category || 0];
},
_getNodeQueryTarget: function (serie, group) {
var category = this._getNodeCategory(serie, group);
return [group, category, serie];
},
_getEdgeQueryTarget: function (serie, edge, type) {
type = type || 'normal';
return [
(edge.itemStyle && edge.itemStyle[type]),
serie.itemStyle[type].chordStyle
];
},
_buildChords: function (series) {
var graphs = [];
var mainSerie = series[0];
var nodeFilter = function (n) {
return n.layout.size > 0;
};
var createEdgeFilter = function (graph) {
return function (e) {
return graph.getEdge(e.node2, e.node1);
};
};
for (var i = 0; i < series.length; i++) {
var serie = series[i];
if (this.selectedMap[serie.name]) {
var graph;
if (serie.data && serie.matrix) {
graph = this._getSerieGraphFromDataMatrix(
serie, mainSerie
);
} else if (serie.nodes && serie.links) {
graph = this._getSerieGraphFromNodeLinks(
serie, mainSerie
);
}
// 过滤输出为0的节点
graph.filterNode(nodeFilter, this);
if (serie.ribbonType) {
graph.filterEdge(createEdgeFilter(graph));
}
graphs.push(graph);
graph.__serie = serie;
}
}
if (!graphs.length) {
return;
}
var mainGraph = graphs[0];
if (!mainSerie.ribbonType) {
var minRadius = mainSerie.minRadius;
var maxRadius = mainSerie.maxRadius;
// Map size to [minRadius, maxRadius]
var min = Infinity, max = -Infinity;
mainGraph.eachNode(function (node) {
max = Math.max(node.layout.size, max);
min = Math.min(node.layout.size, min);
});
var multiplier = (maxRadius - minRadius) / (max - min);
mainGraph.eachNode(function (node) {
var queryTarget = this._getNodeQueryTarget(mainSerie, node);
var symbolSize = this.query(queryTarget, 'symbolSize');
if (max === min) {
node.layout.size = symbolSize || min;
}
else {
node.layout.size = symbolSize
|| (node.layout.size - min) * multiplier + minRadius;
}
}, this);
}
// Do layout
var layout = new ChordLayout();
layout.clockWise = mainSerie.clockWise;
layout.startAngle = mainSerie.startAngle * Math.PI / 180;
if (!layout.clockWise) {
layout.startAngle = -layout.startAngle;
}
layout.padding = mainSerie.padding * Math.PI / 180;
layout.sort = mainSerie.sort;
layout.sortSub = mainSerie.sortSub;
layout.directed = mainSerie.ribbonType;
layout.run(graphs);
var showLabel = this.query(
mainSerie, 'itemStyle.normal.label.show'
);
if (mainSerie.ribbonType) {
this._buildSectors(mainSerie, 0, mainGraph, mainSerie, graphs);
if (showLabel) {
this._buildLabels(mainSerie, 0, mainGraph, mainSerie, graphs);
}
for (var i = 0, j = 0; i < series.length; i++) {
if (this.selectedMap[series[i].name]) {
this._buildRibbons(series, i, graphs[j++], mainSerie);
}
}
if (mainSerie.showScale) {
this._buildScales(mainSerie, 0, mainGraph);
}
}
else {
this._buildNodeIcons(mainSerie, 0, mainGraph, mainSerie, graphs);
if (showLabel) {
this._buildLabels(mainSerie, 0, mainGraph, mainSerie, graphs);
}
for (var i = 0, j = 0; i < series.length; i++) {
if (this.selectedMap[series[i].name]) {
this._buildEdgeCurves(series, i, graphs[j++], mainSerie, mainGraph);
}
}
}
this._initHoverHandler(series, graphs);
},
_getSerieGraphFromDataMatrix: function (serie, mainSerie) {
var nodesData = [];
var count = 0;
var matrix = [];
// 复制一份新的matrix
for (var i = 0; i < serie.matrix.length; i++) {
matrix[i] = serie.matrix[i].slice();
}
var data = serie.data || serie.nodes;
for (var i = 0; i < data.length; i++) {
var node = {};
var group = data[i];
group.rawIndex = i;
for (var key in group) {
// name改为id
if (key === 'name') {
node['id'] = group['name'];
}
else {
node[key] = group[key];
}
}
// legends 选择优先级 category -> group
var category = this._getNodeCategory(mainSerie, group);
var name = category ? category.name : group.name;
this.selectedMap[name] = this.isSelected(name);
if (this.selectedMap[name]) {
nodesData.push(node);
count++;
}
else {
// 过滤legend未选中的数据
matrix.splice(count, 1);
for (var j = 0; j < matrix.length; j++) {
matrix[j].splice(count, 1);
}
}
}
var graph = Graph.fromMatrix(nodesData, matrix, true);
// Prepare layout parameters
graph.eachNode(function (n, idx) {
n.layout = {
size: n.data.outValue
};
n.rawIndex = n.data.rawIndex;
});
graph.eachEdge(function (e) {
e.layout = {
weight: e.data.weight
};
});
return graph;
},
_getSerieGraphFromNodeLinks: function (serie, mainSerie) {
var graph = new Graph(true);
var nodes = serie.data || serie.nodes;
for (var i = 0, len = nodes.length; i < len; i++) {
var n = nodes[i];
if (!n || n.ignore) {
continue;
}
// legends 选择优先级 category -> group
var category = this._getNodeCategory(mainSerie, n);
var name = category ? category.name : n.name;
this.selectedMap[name] = this.isSelected(name);
if (this.selectedMap[name]) {
var node = graph.addNode(n.name, n);
node.rawIndex = i;
}
}
for (var i = 0, len = serie.links.length; i < len; i++) {
var e = serie.links[i];
var n1 = e.source;
var n2 = e.target;
if (typeof(n1) === 'number') {
n1 = nodes[n1];
if (n1) {
n1 = n1.name;
}
}
if (typeof(n2) === 'number') {
n2 = nodes[n2];
if (n2) {
n2 = n2.name;
}
}
var edge = graph.addEdge(n1, n2, e);
if (edge) {
edge.rawIndex = i;
}
}
graph.eachNode(function (n) {
var value = n.data.value;
if (value == null) { // value 是 null 或者 undefined
value = 0;
if (mainSerie.ribbonType) {
// 默认使用所有出边值的和作为节点的大小, 不修改 data 里的数值
for (var i = 0; i < n.outEdges.length; i++) {
value += n.outEdges[i].data.weight || 0;
}
}
else {
// 默认使用所有边值的和作为节点的大小, 不修改 data 里的数值
for (var i = 0; i < n.edges.length; i++) {
value += n.edges[i].data.weight || 0;
}
}
}
n.layout = {
size: value
};
});
graph.eachEdge(function (e) {
e.layout = {
// 默认 weight 为1
weight: e.data.weight == null ? 1 : e.data.weight
};
});
return graph;
},
_initHoverHandler: function (series, graphs) {
var mainSerie = series[0];
var mainGraph = graphs[0];
var self = this;
mainGraph.eachNode(function (node) {
node.shape.onmouseover = function () {
mainGraph.eachNode(function (n) {
n.shape.style.opacity = 0.1;
if (n.labelShape) {
n.labelShape.style.opacity = 0.1;
n.labelShape.modSelf();
}
n.shape.modSelf();
});
for (var i = 0; i < graphs.length; i++) {
for (var j = 0; j < graphs[i].edges.length; j++) {
var e = graphs[i].edges[j];
var queryTarget = self._getEdgeQueryTarget(
graphs[i].__serie, e.data
);
e.shape.style.opacity = self.deepQuery(
queryTarget, 'opacity'
) * 0.1;
e.shape.modSelf();
}
}
node.shape.style.opacity = 1;
if (node.labelShape) {
node.labelShape.style.opacity = 1;
}
for (var i = 0; i < graphs.length; i++) {
var n = graphs[i].getNodeById(node.id);
if (n) { // 节点有可能没数据被过滤掉了
for (var j = 0; j < n.outEdges.length; j++) {
var e = n.outEdges[j];
var queryTarget = self._getEdgeQueryTarget(
graphs[i].__serie, e.data
);
e.shape.style.opacity = self.deepQuery(
queryTarget, 'opacity'
);
var other = graphs[0].getNodeById(e.node2.id);
if (other) {
if (other.shape) {
other.shape.style.opacity = 1;
}
if (other.labelShape) {
other.labelShape.style.opacity = 1;
}
}
}
}
}
self.zr.refreshNextFrame();
};
node.shape.onmouseout = function () {
mainGraph.eachNode(function (n) {
n.shape.style.opacity = 1;
if (n.labelShape) {
n.labelShape.style.opacity = 1;
n.labelShape.modSelf();
}
n.shape.modSelf();
});
for (var i = 0; i < graphs.length; i++) {
for (var j = 0; j < graphs[i].edges.length; j++) {
var e = graphs[i].edges[j];
var queryTarget = [e.data, mainSerie];
e.shape.style.opacity = self.deepQuery(
queryTarget, 'itemStyle.normal.chordStyle.opacity'
);
e.shape.modSelf();
}
}
self.zr.refreshNextFrame();
};
});
},
_buildSectors: function (serie, serieIdx, graph, mainSerie) {
var center = this.parseCenter(this.zr, mainSerie.center);
var radius = this.parseRadius(this.zr, mainSerie.radius);
var clockWise = mainSerie.clockWise;
var sign = clockWise ? 1 : -1;
graph.eachNode(function (node) {
var category = this._getNodeCategory(mainSerie, node.data);
// 默认使用 category 分类颜色
var color = category ? this.getColor(category.name) : this.getColor(node.id);
var startAngle = node.layout.startAngle / Math.PI * 180 * sign;
var endAngle = node.layout.endAngle / Math.PI * 180 * sign;
var sector = new SectorShape({
zlevel: this.getZlevelBase(),
z : this.getZBase(),
style: {
x: center[0],
y: center[1],
r0: radius[0],
r: radius[1],
startAngle: startAngle,
endAngle: endAngle,
brushType: 'fill',
opacity: 1,
color: color,
clockWise: clockWise
},
clickable: mainSerie.clickable,
highlightStyle: {
brushType: 'fill'
}
});
sector.style.lineWidth = this.deepQuery(
[node.data, mainSerie],
'itemStyle.normal.borderWidth'
);
sector.highlightStyle.lineWidth = this.deepQuery(
[node.data, mainSerie],
'itemStyle.emphasis.borderWidth'
);
sector.style.strokeColor = this.deepQuery(
[node.data, mainSerie],
'itemStyle.normal.borderColor'
);
sector.highlightStyle.strokeColor = this.deepQuery(
[node.data, mainSerie],
'itemStyle.emphasis.borderColor'
);
if (sector.style.lineWidth > 0) {
sector.style.brushType = 'both';
}
if (sector.highlightStyle.lineWidth > 0) {
sector.highlightStyle.brushType = 'both';
}
ecData.pack(
sector,
serie,
serieIdx,
node.data,
node.rawIndex,
node.id,
// special
node.category
);
this.shapeList.push(sector);
node.shape = sector;
}, this);
},
_buildNodeIcons: function (serie, serieIdx, graph, mainSerie) {
var center = this.parseCenter(this.zr, mainSerie.center);
var radius = this.parseRadius(this.zr, mainSerie.radius);
// PENDING
var r = radius[1];
graph.eachNode(function (node) {
var startAngle = node.layout.startAngle;
var endAngle = node.layout.endAngle;
var angle = (startAngle + endAngle) / 2;
var x = r * Math.cos(angle);
var y = r * Math.sin(angle);
var queryTarget = this._getNodeQueryTarget(mainSerie, node.data);
var category = this._getNodeCategory(mainSerie, node.data);
var color = this.deepQuery(queryTarget, 'itemStyle.normal.color');
if (!color) {
color = category ? this.getColor(category.name) : this.getColor(node.id);
}
var iconShape = new IconShape({
zlevel: this.getZlevelBase(),
z: this.getZBase() + 1,
style: {
x: - node.layout.size,
y: - node.layout.size,
width: node.layout.size * 2,
height: node.layout.size * 2,
iconType: this.deepQuery(queryTarget, 'symbol'),
color: color,
brushType: 'both',
lineWidth: this.deepQuery(queryTarget, 'itemStyle.normal.borderWidth'),
strokeColor: this.deepQuery(queryTarget, 'itemStyle.normal.borderColor')
},
highlightStyle: {
color: this.deepQuery(queryTarget, 'itemStyle.emphasis.color'),
lineWidth: this.deepQuery(queryTarget, 'itemStyle.emphasis.borderWidth'),
strokeColor: this.deepQuery(queryTarget, 'itemStyle.emphasis.borderColor')
},
clickable: mainSerie.clickable,
position: [x + center[0], y + center[1]]
});
ecData.pack(
iconShape,
serie,
serieIdx,
node.data,
node.rawIndex,
node.id,
// special
node.category
);
this.shapeList.push(iconShape);
node.shape = iconShape;
}, this);
},
_buildLabels: function (serie, serieIdx, graph, mainSerie) {
var labelColor = this.query(
mainSerie, 'itemStyle.normal.label.color'
);
var rotateLabel = this.query(
mainSerie, 'itemStyle.normal.label.rotate'
);
var labelDistance = this.query(
mainSerie, 'itemStyle.normal.label.distance'
);
var center = this.parseCenter(this.zr, mainSerie.center);
var radius = this.parseRadius(this.zr, mainSerie.radius);
var clockWise = mainSerie.clockWise;
var sign = clockWise ? 1 : -1;
graph.eachNode(function (node) {
var startAngle = node.layout.startAngle / Math.PI * 180 * sign;
var endAngle = node.layout.endAngle / Math.PI * 180 * sign;
var angle = (startAngle * -sign + endAngle * -sign) / 2;
angle %= 360;
if (angle < 0) { // Constrain to [0,360]
angle += 360;
}
var isRightSide = angle <= 90
|| angle >= 270;
angle = angle * Math.PI / 180;
var v = [Math.cos(angle), -Math.sin(angle)];
var distance = 0;
if (mainSerie.ribbonType) {
distance = mainSerie.showScaleText ? 35 + labelDistance : labelDistance;
}
else {
distance = labelDistance + node.layout.size;
}
var start = vec2.scale([], v, radius[1] + distance);
vec2.add(start, start, center);
var labelShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase() + 1,
hoverable: false,
style: {
text: node.data.label == null ? node.id : node.data.label,
textAlign: isRightSide ? 'left' : 'right',
color: labelColor || '#000000'
}
};
if (rotateLabel) {
labelShape.rotation = isRightSide ? angle : Math.PI + angle;
if (isRightSide) {
labelShape.style.x = radius[1] + distance;
}
else {
labelShape.style.x = -radius[1] - distance;
}
labelShape.style.y = 0;
labelShape.position = center.slice();
}
else {
labelShape.style.x = start[0];
labelShape.style.y = start[1];
}
labelShape.style.textColor = this.deepQuery(
[node.data, mainSerie],
'itemStyle.normal.label.textStyle.color'
) || '#fff';
labelShape.style.textFont = this.getFont(this.deepQuery(
[node.data, mainSerie],
'itemStyle.normal.label.textStyle'
));
labelShape = new TextShape(labelShape);
this.shapeList.push(labelShape);
node.labelShape = labelShape;
}, this);
},
_buildRibbons : function (series, serieIdx, graph, mainSerie) {
var serie = series[serieIdx];
var center = this.parseCenter(this.zr, mainSerie.center);
var radius = this.parseRadius(this.zr, mainSerie.radius);
// graph.edges.length = 1;
graph.eachEdge(function (edge, idx) {
var color;
// 反向边
var other = graph.getEdge(edge.node2, edge.node1);
if (!other // 只有单边
|| edge.shape // 已经创建过Ribbon
) {
return;
}
if (other.shape) { // 已经创建过Ribbon
edge.shape = other.shape;
return;
}
var s0 = edge.layout.startAngle / Math.PI * 180;
var s1 = edge.layout.endAngle / Math.PI * 180;
var t0 = other.layout.startAngle / Math.PI * 180;
var t1 = other.layout.endAngle / Math.PI * 180;
if (series.length === 1) {
// 取小端的颜色
if (edge.layout.weight <= other.layout.weight) {
color = this.getColor(edge.node1.id);
}
else {
color = this.getColor(edge.node2.id);
}
} else {
// 使用系列颜色
color = this.getColor(serie.name);
}
var queryTarget = this._getEdgeQueryTarget(serie, edge.data);
var queryTargetEmphasis = this._getEdgeQueryTarget(
serie, edge.data, 'emphasis'
);
var ribbon = new RibbonShape({
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style: {
x: center[0],
y: center[1],
r: radius[0],
source0: s0,
source1: s1,
target0: t0,
target1: t1,
brushType: 'both',
opacity: this.deepQuery(
queryTarget, 'opacity'
),
color: color,
lineWidth: this.deepQuery(queryTarget, 'borderWidth'),
strokeColor: this.deepQuery(queryTarget, 'borderColor'),
clockWise: mainSerie.clockWise
},
clickable: mainSerie.clickable,
highlightStyle: {
brushType: 'both',
opacity: this.deepQuery(
queryTargetEmphasis, 'opacity'
),
lineWidth: this.deepQuery(queryTargetEmphasis, 'borderWidth'),
strokeColor: this.deepQuery(queryTargetEmphasis, 'borderColor')
}
});
var node1, node2;
// 从大端到小端
if (edge.layout.weight <= other.layout.weight) {
node1 = other.node1;
node2 = other.node2;
} else {
node1 = edge.node1;
node2 = edge.node2;
}
ecData.pack(
ribbon,
serie,
serieIdx,
edge.data,
edge.rawIndex == null ? idx : edge.rawIndex,
edge.data.name || (node1.id + '-' + node2.id),
// special
node1.id,
// special2
node2.id
);
this.shapeList.push(ribbon);
edge.shape = ribbon;
}, this);
},
_buildEdgeCurves: function (series, serieIdx, graph, mainSerie, mainGraph) {
var serie = series[serieIdx];
var center = this.parseCenter(this.zr, mainSerie.center);
graph.eachEdge(function (e, idx) {
var node1 = mainGraph.getNodeById(e.node1.id);
var node2 = mainGraph.getNodeById(e.node2.id);
var shape1 = node1.shape;
var shape2 = node2.shape;
var queryTarget = this._getEdgeQueryTarget(serie, e.data);
var queryTargetEmphasis = this._getEdgeQueryTarget(
serie, e.data, 'emphasis'
);
var curveShape = new BezierCurveShape({
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style: {
xStart: shape1.position[0],
yStart: shape1.position[1],
xEnd: shape2.position[0],
yEnd: shape2.position[1],
cpX1: center[0],
cpY1: center[1],
lineWidth: this.deepQuery(
queryTarget, 'width'
),
strokeColor: this.deepQuery(
queryTarget, 'color'
),
opacity: this.deepQuery(
queryTarget, 'opacity'
)
},
highlightStyle: {
lineWidth: this.deepQuery(
queryTargetEmphasis, 'width'
),
strokeColor: this.deepQuery(
queryTargetEmphasis, 'color'
),
opacity: this.deepQuery(
queryTargetEmphasis, 'opacity'
)
}
});
ecData.pack(
curveShape,
serie,
serieIdx,
e.data,
e.rawIndex == null ? idx : e.rawIndex,
e.data.name || (e.node1.id + '-' + e.node2.id),
// special
e.node1.id,
// special2
e.node2.id
);
this.shapeList.push(curveShape);
e.shape = curveShape;
}, this);
},
_buildScales: function (serie, serieIdx, graph) {
var clockWise = serie.clockWise;
var center = this.parseCenter(this.zr, serie.center);
var radius = this.parseRadius(this.zr, serie.radius);
var sign = clockWise ? 1 : -1;
var sumValue = 0;
var maxValue = -Infinity;
var unitPostfix;
var unitScale;
if (serie.showScaleText) {
graph.eachNode(function (node) {
var val = node.data.value;
if (val > maxValue) {
maxValue = val;
}
sumValue += val;
});
if (maxValue > 1e10) {
unitPostfix = 'b';
unitScale = 1e-9;
}
else if (maxValue > 1e7) {
unitPostfix = 'm';
unitScale = 1e-6;
}
else if (maxValue > 1e4) {
unitPostfix = 'k';
unitScale = 1e-3;
}
else {
unitPostfix = '';
unitScale = 1;
}
}
var unitValue = sumValue / (360 - serie.padding);
graph.eachNode(function (node) {
var startAngle = node.layout.startAngle / Math.PI * 180;
var endAngle = node.layout.endAngle / Math.PI * 180;
var scaleAngle = startAngle;
while (true) {
if ((clockWise && scaleAngle > endAngle)
|| (!clockWise && scaleAngle < endAngle)
) {
break;
}
var theta = scaleAngle / 180 * Math.PI;
var v = [Math.cos(theta), Math.sin(theta)];
var start = vec2.scale([], v, radius[1] + 1);
vec2.add(start, start, center);
var end = vec2.scale([], v, radius[1] + this.scaleLineLength);
vec2.add(end, end, center);
var scaleShape = new LineShape({
zlevel: this.getZlevelBase(),
z: this.getZBase() - 1,
hoverable: false,
style: {
xStart: start[0],
yStart: start[1],
xEnd: end[0],
yEnd: end[1],
lineCap: 'round',
brushType: 'stroke',
strokeColor: '#666',
lineWidth: 1
}
});
this.shapeList.push(scaleShape);
scaleAngle += sign * this.scaleUnitAngle;
}
if (!serie.showScaleText) {
return;
}
var scaleTextAngle = startAngle;
var step = unitValue * 5 * this.scaleUnitAngle;
var scaleValue = 0;
while (true) {
if ((clockWise && scaleTextAngle > endAngle)
|| (!clockWise && scaleTextAngle < endAngle)
) {
break;
}
var theta = scaleTextAngle;
theta = theta % 360;
if (theta < 0) {
theta += 360;
}
var isRightSide = theta <= 90
|| theta >= 270;
var textShape = new TextShape({
zlevel: this.getZlevelBase(),
z: this.getZBase() - 1,
hoverable: false,
style: {
x: isRightSide
? radius[1] + this.scaleLineLength + 4
: -radius[1] - this.scaleLineLength - 4,
y: 0,
text: Math.round(scaleValue * 10) / 10
+ unitPostfix,
textAlign: isRightSide ? 'left' : 'right'
},
position: center.slice(),
rotation: isRightSide
? [-theta / 180 * Math.PI, 0, 0]
: [
-(theta + 180) / 180 * Math.PI,
0, 0
]
});
this.shapeList.push(textShape);
scaleValue += step * unitScale;
scaleTextAngle += sign * this.scaleUnitAngle * 5;
}
}, this);
},
refresh : function (newOption) {
if (newOption) {
this.option = newOption;
this.series = newOption.series;
}
this.legend = this.component.legend;
if (this.legend) {
this.getColor = function(param) {
return this.legend.getColor(param);
};
this.isSelected = function(param) {
return this.legend.isSelected(param);
};
}
else {
var colorMap = {};
var count = 0;
this.getColor = function (key) {
if (colorMap[key]) {
return colorMap[key];
}
if (!colorMap[key]) {
colorMap[key] = this.zr.getColor(count++);
}
return colorMap[key];
};
this.isSelected = function () {
return true;
};
}
this.backupShapeList();
this._init();
},
reformOption : function (opt) {
var _merge = zrUtil.merge;
opt = _merge(
_merge(
opt || {},
this.ecTheme.chord
),
ecConfig.chord
);
opt.itemStyle.normal.label.textStyle = this.getTextStyle(
opt.itemStyle.normal.label.textStyle
);
this.z = opt.z;
this.zlevel = opt.zlevel;
}
};
zrUtil.inherits(Chord, ChartBase);
// 图表注册
require('../chart').define('chord', Chord);
return Chord;
});