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; });