1254 lines
50 KiB
JavaScript
1254 lines
50 KiB
JavaScript
define('echarts/chart/chord', [
|
|
'require',
|
|
'./base',
|
|
'zrender/shape/Text',
|
|
'zrender/shape/Line',
|
|
'zrender/shape/Sector',
|
|
'../util/shape/Ribbon',
|
|
'../util/shape/Icon',
|
|
'zrender/shape/BezierCurve',
|
|
'../config',
|
|
'../util/ecData',
|
|
'zrender/tool/util',
|
|
'zrender/tool/vector',
|
|
'../data/Graph',
|
|
'../layout/Chord',
|
|
'../chart'
|
|
], 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',
|
|
sortSub: 'none',
|
|
startAngle: 90,
|
|
clockWise: true,
|
|
ribbonType: true,
|
|
minRadius: 10,
|
|
maxRadius: 20,
|
|
symbol: 'circle',
|
|
showScale: false,
|
|
showScaleText: false,
|
|
itemStyle: {
|
|
normal: {
|
|
borderWidth: 0,
|
|
borderColor: '#000',
|
|
label: {
|
|
show: true,
|
|
rotate: false,
|
|
distance: 5
|
|
},
|
|
chordStyle: {
|
|
width: 1,
|
|
color: 'black',
|
|
borderWidth: 1,
|
|
borderColor: '#999',
|
|
opacity: 0.5
|
|
}
|
|
},
|
|
emphasis: {
|
|
borderWidth: 0,
|
|
borderColor: '#000',
|
|
chordStyle: {
|
|
width: 1,
|
|
color: 'black',
|
|
borderWidth: 1,
|
|
borderColor: '#999'
|
|
}
|
|
}
|
|
}
|
|
};
|
|
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);
|
|
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) {
|
|
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.matrix) {
|
|
graph = this._getSerieGraphFromDataMatrix(serie, mainSerie);
|
|
} else if (serie.links) {
|
|
graph = this._getSerieGraphFromNodeLinks(serie, mainSerie);
|
|
}
|
|
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;
|
|
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);
|
|
}
|
|
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 = [];
|
|
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) {
|
|
if (key === 'name') {
|
|
node['id'] = group['name'];
|
|
} else {
|
|
node[key] = group[key];
|
|
}
|
|
}
|
|
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 {
|
|
matrix.splice(count, 1);
|
|
for (var j = 0; j < matrix.length; j++) {
|
|
matrix[j].splice(count, 1);
|
|
}
|
|
}
|
|
}
|
|
var graph = Graph.fromMatrix(nodesData, matrix, true);
|
|
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;
|
|
}
|
|
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 = 0;
|
|
if (mainSerie.ribbonType) {
|
|
for (var i = 0; i < n.outEdges.length; i++) {
|
|
value += n.outEdges[i].data.weight || 0;
|
|
}
|
|
} else {
|
|
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: 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);
|
|
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: serie.zlevel,
|
|
z: serie.z,
|
|
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, 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);
|
|
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: serie.zlevel,
|
|
z: serie.z + 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, node.category);
|
|
this.shapeList.push(iconShape);
|
|
node.shape = iconShape;
|
|
}, this);
|
|
},
|
|
_buildLabels: function (serie, serieIdx, graph, mainSerie) {
|
|
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) {
|
|
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: serie.zlevel,
|
|
z: serie.z + 1,
|
|
hoverable: false,
|
|
style: {
|
|
text: node.data.label == null ? node.id : node.data.label,
|
|
textAlign: isRightSide ? 'left' : 'right'
|
|
}
|
|
};
|
|
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.color = this.deepQuery([
|
|
node.data,
|
|
mainSerie
|
|
], 'itemStyle.normal.label.textStyle.color') || '#000000';
|
|
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.eachEdge(function (edge, idx) {
|
|
var color;
|
|
var other = graph.getEdge(edge.node2, edge.node1);
|
|
if (!other || edge.shape) {
|
|
return;
|
|
}
|
|
if (other.shape) {
|
|
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: serie.zlevel,
|
|
z: serie.z,
|
|
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, node1.id, 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: serie.zlevel,
|
|
z: serie.z,
|
|
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, e.node1.id, 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 > 10000000000) {
|
|
unitPostfix = 'b';
|
|
unitScale = 1e-9;
|
|
} else if (maxValue > 10000000) {
|
|
unitPostfix = 'm';
|
|
unitScale = 0.000001;
|
|
} else if (maxValue > 10000) {
|
|
unitPostfix = 'k';
|
|
unitScale = 0.001;
|
|
} 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: serie.zlevel,
|
|
z: serie.z - 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: serie.zlevel,
|
|
z: serie.z - 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;
|
|
});define('echarts/util/shape/Ribbon', [
|
|
'require',
|
|
'zrender/shape/Base',
|
|
'zrender/shape/util/PathProxy',
|
|
'zrender/tool/util',
|
|
'zrender/tool/area'
|
|
], function (require) {
|
|
var Base = require('zrender/shape/Base');
|
|
var PathProxy = require('zrender/shape/util/PathProxy');
|
|
var zrUtil = require('zrender/tool/util');
|
|
var area = require('zrender/tool/area');
|
|
function RibbonShape(options) {
|
|
Base.call(this, options);
|
|
this._pathProxy = new PathProxy();
|
|
}
|
|
RibbonShape.prototype = {
|
|
type: 'ribbon',
|
|
buildPath: function (ctx, style) {
|
|
var clockWise = style.clockWise || false;
|
|
var path = this._pathProxy;
|
|
path.begin(ctx);
|
|
var cx = style.x;
|
|
var cy = style.y;
|
|
var r = style.r;
|
|
var s0 = style.source0 / 180 * Math.PI;
|
|
var s1 = style.source1 / 180 * Math.PI;
|
|
var t0 = style.target0 / 180 * Math.PI;
|
|
var t1 = style.target1 / 180 * Math.PI;
|
|
var sx0 = cx + Math.cos(s0) * r;
|
|
var sy0 = cy + Math.sin(s0) * r;
|
|
var sx1 = cx + Math.cos(s1) * r;
|
|
var sy1 = cy + Math.sin(s1) * r;
|
|
var tx0 = cx + Math.cos(t0) * r;
|
|
var ty0 = cy + Math.sin(t0) * r;
|
|
var tx1 = cx + Math.cos(t1) * r;
|
|
var ty1 = cy + Math.sin(t1) * r;
|
|
path.moveTo(sx0, sy0);
|
|
path.arc(cx, cy, style.r, s0, s1, !clockWise);
|
|
path.bezierCurveTo((cx - sx1) * 0.7 + sx1, (cy - sy1) * 0.7 + sy1, (cx - tx0) * 0.7 + tx0, (cy - ty0) * 0.7 + ty0, tx0, ty0);
|
|
if (style.source0 === style.target0 && style.source1 === style.target1) {
|
|
return;
|
|
}
|
|
path.arc(cx, cy, style.r, t0, t1, !clockWise);
|
|
path.bezierCurveTo((cx - tx1) * 0.7 + tx1, (cy - ty1) * 0.7 + ty1, (cx - sx0) * 0.7 + sx0, (cy - sy0) * 0.7 + sy0, sx0, sy0);
|
|
},
|
|
getRect: function (style) {
|
|
if (style.__rect) {
|
|
return style.__rect;
|
|
}
|
|
if (!this._pathProxy.isEmpty()) {
|
|
this.buildPath(null, style);
|
|
}
|
|
return this._pathProxy.fastBoundingRect();
|
|
},
|
|
isCover: function (x, y) {
|
|
var rect = this.getRect(this.style);
|
|
if (x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height) {
|
|
return area.isInsidePath(this._pathProxy.pathCommands, 0, 'fill', x, y);
|
|
}
|
|
}
|
|
};
|
|
zrUtil.inherits(RibbonShape, Base);
|
|
return RibbonShape;
|
|
});define('echarts/data/Graph', [
|
|
'require',
|
|
'zrender/tool/util'
|
|
], function (require) {
|
|
var util = require('zrender/tool/util');
|
|
'use strict';
|
|
var Graph = function (directed) {
|
|
this._directed = directed || false;
|
|
this.nodes = [];
|
|
this.edges = [];
|
|
this._nodesMap = {};
|
|
this._edgesMap = {};
|
|
};
|
|
Graph.prototype.isDirected = function () {
|
|
return this._directed;
|
|
};
|
|
Graph.prototype.addNode = function (id, data) {
|
|
if (this._nodesMap[id]) {
|
|
return this._nodesMap[id];
|
|
}
|
|
var node = new Graph.Node(id, data);
|
|
this.nodes.push(node);
|
|
this._nodesMap[id] = node;
|
|
return node;
|
|
};
|
|
Graph.prototype.getNodeById = function (id) {
|
|
return this._nodesMap[id];
|
|
};
|
|
Graph.prototype.addEdge = function (n1, n2, data) {
|
|
if (typeof n1 == 'string') {
|
|
n1 = this._nodesMap[n1];
|
|
}
|
|
if (typeof n2 == 'string') {
|
|
n2 = this._nodesMap[n2];
|
|
}
|
|
if (!n1 || !n2) {
|
|
return;
|
|
}
|
|
var key = n1.id + '-' + n2.id;
|
|
if (this._edgesMap[key]) {
|
|
return this._edgesMap[key];
|
|
}
|
|
var edge = new Graph.Edge(n1, n2, data);
|
|
if (this._directed) {
|
|
n1.outEdges.push(edge);
|
|
n2.inEdges.push(edge);
|
|
}
|
|
n1.edges.push(edge);
|
|
if (n1 !== n2) {
|
|
n2.edges.push(edge);
|
|
}
|
|
this.edges.push(edge);
|
|
this._edgesMap[key] = edge;
|
|
return edge;
|
|
};
|
|
Graph.prototype.removeEdge = function (edge) {
|
|
var n1 = edge.node1;
|
|
var n2 = edge.node2;
|
|
var key = n1.id + '-' + n2.id;
|
|
if (this._directed) {
|
|
n1.outEdges.splice(util.indexOf(n1.outEdges, edge), 1);
|
|
n2.inEdges.splice(util.indexOf(n2.inEdges, edge), 1);
|
|
}
|
|
n1.edges.splice(util.indexOf(n1.edges, edge), 1);
|
|
if (n1 !== n2) {
|
|
n2.edges.splice(util.indexOf(n2.edges, edge), 1);
|
|
}
|
|
delete this._edgesMap[key];
|
|
this.edges.splice(util.indexOf(this.edges, edge), 1);
|
|
};
|
|
Graph.prototype.getEdge = function (n1, n2) {
|
|
if (typeof n1 !== 'string') {
|
|
n1 = n1.id;
|
|
}
|
|
if (typeof n2 !== 'string') {
|
|
n2 = n2.id;
|
|
}
|
|
if (this._directed) {
|
|
return this._edgesMap[n1 + '-' + n2];
|
|
} else {
|
|
return this._edgesMap[n1 + '-' + n2] || this._edgesMap[n2 + '-' + n1];
|
|
}
|
|
};
|
|
Graph.prototype.removeNode = function (node) {
|
|
if (typeof node === 'string') {
|
|
node = this._nodesMap[node];
|
|
if (!node) {
|
|
return;
|
|
}
|
|
}
|
|
delete this._nodesMap[node.id];
|
|
this.nodes.splice(util.indexOf(this.nodes, node), 1);
|
|
for (var i = 0; i < this.edges.length;) {
|
|
var edge = this.edges[i];
|
|
if (edge.node1 === node || edge.node2 === node) {
|
|
this.removeEdge(edge);
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.filterNode = function (cb, context) {
|
|
var len = this.nodes.length;
|
|
for (var i = 0; i < len;) {
|
|
if (cb.call(context, this.nodes[i], i)) {
|
|
i++;
|
|
} else {
|
|
this.removeNode(this.nodes[i]);
|
|
len--;
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.filterEdge = function (cb, context) {
|
|
var len = this.edges.length;
|
|
for (var i = 0; i < len;) {
|
|
if (cb.call(context, this.edges[i], i)) {
|
|
i++;
|
|
} else {
|
|
this.removeEdge(this.edges[i]);
|
|
len--;
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.eachNode = function (cb, context) {
|
|
var len = this.nodes.length;
|
|
for (var i = 0; i < len; i++) {
|
|
if (this.nodes[i]) {
|
|
cb.call(context, this.nodes[i], i);
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.eachEdge = function (cb, context) {
|
|
var len = this.edges.length;
|
|
for (var i = 0; i < len; i++) {
|
|
if (this.edges[i]) {
|
|
cb.call(context, this.edges[i], i);
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.clear = function () {
|
|
this.nodes.length = 0;
|
|
this.edges.length = 0;
|
|
this._nodesMap = {};
|
|
this._edgesMap = {};
|
|
};
|
|
Graph.prototype.breadthFirstTraverse = function (cb, startNode, direction, context) {
|
|
if (typeof startNode === 'string') {
|
|
startNode = this._nodesMap[startNode];
|
|
}
|
|
if (!startNode) {
|
|
return;
|
|
}
|
|
var edgeType = 'edges';
|
|
if (direction === 'out') {
|
|
edgeType = 'outEdges';
|
|
} else if (direction === 'in') {
|
|
edgeType = 'inEdges';
|
|
}
|
|
for (var i = 0; i < this.nodes.length; i++) {
|
|
this.nodes[i].__visited = false;
|
|
}
|
|
if (cb.call(context, startNode, null)) {
|
|
return;
|
|
}
|
|
var queue = [startNode];
|
|
while (queue.length) {
|
|
var currentNode = queue.shift();
|
|
var edges = currentNode[edgeType];
|
|
for (var i = 0; i < edges.length; i++) {
|
|
var e = edges[i];
|
|
var otherNode = e.node1 === currentNode ? e.node2 : e.node1;
|
|
if (!otherNode.__visited) {
|
|
if (cb.call(otherNode, otherNode, currentNode)) {
|
|
return;
|
|
}
|
|
queue.push(otherNode);
|
|
otherNode.__visited = true;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Graph.prototype.clone = function () {
|
|
var graph = new Graph(this._directed);
|
|
for (var i = 0; i < this.nodes.length; i++) {
|
|
graph.addNode(this.nodes[i].id, this.nodes[i].data);
|
|
}
|
|
for (var i = 0; i < this.edges.length; i++) {
|
|
var e = this.edges[i];
|
|
graph.addEdge(e.node1.id, e.node2.id, e.data);
|
|
}
|
|
return graph;
|
|
};
|
|
var Node = function (id, data) {
|
|
this.id = id;
|
|
this.data = data || null;
|
|
this.inEdges = [];
|
|
this.outEdges = [];
|
|
this.edges = [];
|
|
};
|
|
Node.prototype.degree = function () {
|
|
return this.edges.length;
|
|
};
|
|
Node.prototype.inDegree = function () {
|
|
return this.inEdges.length;
|
|
};
|
|
Node.prototype.outDegree = function () {
|
|
return this.outEdges.length;
|
|
};
|
|
var Edge = function (node1, node2, data) {
|
|
this.node1 = node1;
|
|
this.node2 = node2;
|
|
this.data = data || null;
|
|
};
|
|
Graph.Node = Node;
|
|
Graph.Edge = Edge;
|
|
Graph.fromMatrix = function (nodesData, matrix, directed) {
|
|
if (!matrix || !matrix.length || matrix[0].length !== matrix.length || nodesData.length !== matrix.length) {
|
|
return;
|
|
}
|
|
var size = matrix.length;
|
|
var graph = new Graph(directed);
|
|
for (var i = 0; i < size; i++) {
|
|
var node = graph.addNode(nodesData[i].id, nodesData[i]);
|
|
node.data.value = 0;
|
|
if (directed) {
|
|
node.data.outValue = node.data.inValue = 0;
|
|
}
|
|
}
|
|
for (var i = 0; i < size; i++) {
|
|
for (var j = 0; j < size; j++) {
|
|
var item = matrix[i][j];
|
|
if (directed) {
|
|
graph.nodes[i].data.outValue += item;
|
|
graph.nodes[j].data.inValue += item;
|
|
}
|
|
graph.nodes[i].data.value += item;
|
|
graph.nodes[j].data.value += item;
|
|
}
|
|
}
|
|
for (var i = 0; i < size; i++) {
|
|
for (var j = i; j < size; j++) {
|
|
var item = matrix[i][j];
|
|
if (item === 0) {
|
|
continue;
|
|
}
|
|
var n1 = graph.nodes[i];
|
|
var n2 = graph.nodes[j];
|
|
var edge = graph.addEdge(n1, n2, {});
|
|
edge.data.weight = item;
|
|
if (i !== j) {
|
|
if (directed && matrix[j][i]) {
|
|
var inEdge = graph.addEdge(n2, n1, {});
|
|
inEdge.data.weight = matrix[j][i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return graph;
|
|
};
|
|
return Graph;
|
|
});define('echarts/layout/Chord', ['require'], function (require) {
|
|
var ChordLayout = function (opts) {
|
|
opts = opts || {};
|
|
this.sort = opts.sort || null;
|
|
this.sortSub = opts.sortSub || null;
|
|
this.padding = 0.05;
|
|
this.startAngle = opts.startAngle || 0;
|
|
this.clockWise = opts.clockWise == null ? false : opts.clockWise;
|
|
this.center = opts.center || [
|
|
0,
|
|
0
|
|
];
|
|
this.directed = true;
|
|
};
|
|
ChordLayout.prototype.run = function (graphs) {
|
|
if (!(graphs instanceof Array)) {
|
|
graphs = [graphs];
|
|
}
|
|
var gl = graphs.length;
|
|
if (!gl) {
|
|
return;
|
|
}
|
|
var graph0 = graphs[0];
|
|
var nl = graph0.nodes.length;
|
|
var groups = [];
|
|
var sumSize = 0;
|
|
for (var i = 0; i < nl; i++) {
|
|
var g0node = graph0.nodes[i];
|
|
var group = {
|
|
size: 0,
|
|
subGroups: [],
|
|
node: g0node
|
|
};
|
|
groups.push(group);
|
|
var sumWeight = 0;
|
|
for (var k = 0; k < graphs.length; k++) {
|
|
var graph = graphs[k];
|
|
var node = graph.getNodeById(g0node.id);
|
|
if (!node) {
|
|
continue;
|
|
}
|
|
group.size += node.layout.size;
|
|
var edges = this.directed ? node.outEdges : node.edges;
|
|
for (var j = 0; j < edges.length; j++) {
|
|
var e = edges[j];
|
|
var w = e.layout.weight;
|
|
group.subGroups.push({
|
|
weight: w,
|
|
edge: e,
|
|
graph: graph
|
|
});
|
|
sumWeight += w;
|
|
}
|
|
}
|
|
sumSize += group.size;
|
|
var multiplier = group.size / sumWeight;
|
|
for (var j = 0; j < group.subGroups.length; j++) {
|
|
group.subGroups[j].weight *= multiplier;
|
|
}
|
|
if (this.sortSub === 'ascending') {
|
|
group.subGroups.sort(compareSubGroups);
|
|
} else if (this.sort === 'descending') {
|
|
group.subGroups.sort(compareSubGroups);
|
|
group.subGroups.reverse();
|
|
}
|
|
}
|
|
if (this.sort === 'ascending') {
|
|
groups.sort(compareGroups);
|
|
} else if (this.sort === 'descending') {
|
|
groups.sort(compareGroups);
|
|
groups.reverse();
|
|
}
|
|
var multiplier = (Math.PI * 2 - this.padding * nl) / sumSize;
|
|
var angle = this.startAngle;
|
|
var sign = this.clockWise ? 1 : -1;
|
|
for (var i = 0; i < nl; i++) {
|
|
var group = groups[i];
|
|
group.node.layout.startAngle = angle;
|
|
group.node.layout.endAngle = angle + sign * group.size * multiplier;
|
|
group.node.layout.subGroups = [];
|
|
for (var j = 0; j < group.subGroups.length; j++) {
|
|
var subGroup = group.subGroups[j];
|
|
subGroup.edge.layout.startAngle = angle;
|
|
angle += sign * subGroup.weight * multiplier;
|
|
subGroup.edge.layout.endAngle = angle;
|
|
}
|
|
angle = group.node.layout.endAngle + sign * this.padding;
|
|
}
|
|
};
|
|
var compareSubGroups = function (a, b) {
|
|
return a.weight - b.weight;
|
|
};
|
|
var compareGroups = function (a, b) {
|
|
return a.size - b.size;
|
|
};
|
|
return ChordLayout;
|
|
}); |