123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098 |
- /**
- * 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;
- // matrix 表示边
- if (serie.matrix) {
- graph = this._getSerieGraphFromDataMatrix(
- serie, mainSerie
- );
- }
- // links 表示边
- else if (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: 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,
- // 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: 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,
- // 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: 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];
- }
- // zrender/Text并没有textColor属性,ctx fillStyle使用的是color
- 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.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: 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),
- // 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: 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),
- // 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: 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;
- });
|