From 4dfd5d149c61bad5b26e65d031e68383e8712408 Mon Sep 17 00:00:00 2001 From: lang <bm2736892@gmail.com> Date: Thu, 30 Oct 2014 12:29:16 +0800 Subject: [PATCH] =?UTF-8?q?chord=20=E6=94=AF=E6=8C=81=20category,=20force?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E9=85=8D=E7=BD=AE=20stroke(=E5=85=BC?= =?UTF-8?q?=E5=AE=B9)=20->=20border?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/example/chord3.html | 2 +- doc/example/chord4.html | 32 ++++---- doc/example/force.html | 5 +- doc/example/force1.html | 4 +- doc/example/force2.html | 4 +- doc/example/webkit-dep2.html | 149 +++++++++++++++++++++++++++++++++++ src/chart/chord.js | 61 ++++++++++---- src/chart/force.js | 18 +++++ src/component/legend.js | 5 +- src/config.js | 24 +++++- 10 files changed, 260 insertions(+), 44 deletions(-) create mode 100644 doc/example/webkit-dep2.html diff --git a/doc/example/chord3.html b/doc/example/chord3.html index f515b1c508..a015c3f1c6 100644 --- a/doc/example/chord3.html +++ b/doc/example/chord3.html @@ -122,7 +122,7 @@ {target: '多特蒙德', source: '胡梅尔斯', weight: 1}, {target: '多特蒙德', source: '魏登费勒', weight: 1}, {target: '多特蒙德', source: '杜尔姆', weight: 1}, - {target: '多特蒙德', source: '格罗斯克罗伊茨', weight: 1}, + {target: '多特蒙德', source: '格罗斯克罗伊茨', weight: 1} ] } ] diff --git a/doc/example/chord4.html b/doc/example/chord4.html index f9a7f6a403..e808e3d302 100644 --- a/doc/example/chord4.html +++ b/doc/example/chord4.html @@ -74,6 +74,8 @@ } } }, + minRadius: 7, + maxRadius: 20, // 使用 nodes links 表达和弦图 nodes: [ {name:'默特萨克'}, @@ -84,7 +86,7 @@ {name:'施魏因施泰格'}, {name:'拉姆'}, {name:'克罗斯'}, - {name:'穆勒'}, + {name:'穆勒', symbol: 'star'}, {name:'格策'}, {name:'胡梅尔斯'}, {name:'魏登费勒'}, @@ -95,20 +97,20 @@ {name:'多特蒙德'} ], links: [ - {source: '阿森纳', target: '默特萨克', weight: 0.9}, - {source: '阿森纳', target: '厄齐尔', weight: 0.9}, - {source: '阿森纳', target: '波多尔斯基', weight: 0.9}, - {source: '拜仁慕尼黑', target: '诺伊尔', weight: 0.9}, - {source: '拜仁慕尼黑', target: '博阿滕', weight: 0.9}, - {source: '拜仁慕尼黑', target: '施魏因施泰格', weight: 0.9}, - {source: '拜仁慕尼黑', target: '拉姆', weight: 0.9}, - {source: '拜仁慕尼黑', target: '克罗斯', weight: 0.9}, - {source: '拜仁慕尼黑', target: '穆勒', weight: 0.9}, - {source: '拜仁慕尼黑', target: '格策', weight: 0.9}, - {source: '多特蒙德', target: '胡梅尔斯', weight: 0.9}, - {source: '多特蒙德', target: '魏登费勒', weight: 0.9}, - {source: '多特蒙德', target: '杜尔姆', weight: 0.9}, - {source: '多特蒙德', target: '格罗斯克罗伊茨', weight: 0.9}, + {source: '阿森纳', target: '默特萨克', weight: 1}, + {source: '阿森纳', target: '厄齐尔', weight: 1}, + {source: '阿森纳', target: '波多尔斯基', weight: 1}, + {source: '拜仁慕尼黑', target: '诺伊尔', weight: 1}, + {source: '拜仁慕尼黑', target: '博阿滕', weight: 1}, + {source: '拜仁慕尼黑', target: '施魏因施泰格', weight: 1}, + {source: '拜仁慕尼黑', target: '拉姆', weight: 1}, + {source: '拜仁慕尼黑', target: '克罗斯', weight: 1}, + {source: '拜仁慕尼黑', target: '穆勒', weight: 1}, + {source: '拜仁慕尼黑', target: '格策', weight: 1}, + {source: '多特蒙德', target: '胡梅尔斯', weight: 1}, + {source: '多特蒙德', target: '魏登费勒', weight: 1}, + {source: '多特蒙德', target: '杜尔姆', weight: 1}, + {source: '多特蒙德', target: '格罗斯克罗伊茨', weight: 1} ] } ] diff --git a/doc/example/force.html b/doc/example/force.html index 6c638eb247..9b9fe062b8 100644 --- a/doc/example/force.html +++ b/doc/example/force.html @@ -87,8 +87,8 @@ }, nodeStyle : { brushType : 'both', - strokeColor : 'rgba(255,215,0,0.4)', - lineWidth : 1 + borderColor : 'rgba(255,215,0,0.4)', + borderWidth : 1 } }, emphasis: { @@ -110,6 +110,7 @@ linkSymbol: 'arrow', steps: 10, coolDown: 0.9, + preventOverlap: true, nodes:[ { category:0, name: '乔布斯', value : 10, diff --git a/doc/example/force1.html b/doc/example/force1.html index 7571bfc9a1..42e93fbf20 100644 --- a/doc/example/force1.html +++ b/doc/example/force1.html @@ -86,8 +86,8 @@ }, nodeStyle : { brushType : 'both', - strokeColor : 'rgba(255,215,0,0.4)', - lineWidth : 1 + borderColor : 'rgba(255,215,0,0.4)', + borderWidth : 1 } }, emphasis: { diff --git a/doc/example/force2.html b/doc/example/force2.html index 159bf25f8b..9e7dc83952 100644 --- a/doc/example/force2.html +++ b/doc/example/force2.html @@ -143,8 +143,8 @@ }, nodeStyle : { brushType : 'both', - strokeColor : 'rgba(255,215,0,0.6)', - lineWidth : 1 + borderColor : 'rgba(255,215,0,0.6)', + borderWidth : 1 } } }, diff --git a/doc/example/webkit-dep2.html b/doc/example/webkit-dep2.html new file mode 100644 index 0000000000..e7ba04f1b4 --- /dev/null +++ b/doc/example/webkit-dep2.html @@ -0,0 +1,149 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="description" content="ECharts"> + <meta name="author" content="linzhifeng@baidu.com"> + <title>ECharts · Example</title> + + <link rel="shortcut icon" href="../asset/ico/favicon.png"> + + <link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"> + <link href="../asset/css/bootstrap.css" rel="stylesheet"> + <link href="../asset/css/carousel.css" rel="stylesheet"> + <link href="../asset/css/echartsHome.css" rel="stylesheet"> + <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + + <script src="../asset/js/esl/esl.js"></script> + <script src="../asset/js/codemirror.js"></script> + <script src="../asset/js/javascript.js"></script> + + <link href="../asset/css/codemirror.css" rel="stylesheet"> + <link href="../asset/css/monokai.css" rel="stylesheet"> + <style type="text/css"> + .CodeMirror { + height: 620px; + } + </style> +</head> + +<body> + <!-- Fixed navbar --> + <div class="navbar navbar-default navbar-fixed-top" role="navigation" id="head"></div> + + + <div class="container-fluid"> + <div class="row-fluid example"> + <div id="sidebar-code" class="col-md-1"> + <div class="well sidebar-nav"> + <div class="nav-header"><a href="#" onclick="autoResize()" class="glyphicon glyphicon-resize-full" id ="icon-resize" ></a>option</div> + <textarea id="code" name="code"> +option = { + title : { + text: 'webkit内核依赖', + subtext: '数据来自网络', + x:'right', + y:'bottom' + }, + tooltip : { + trigger: 'item', + formatter : "{b}" + }, + toolbox: { + show : true, + feature : { + restore : {show: true}, + saveAsImage : {show: true} + } + }, + legend : { + data : ['HTMLElement', 'WebGL', 'SVG', 'CSS', 'Other'], + orient : 'vertical', + x : 'left' + }, + series : (function (){ + // If data have been loaded + if (webkitDepData) { + //webkitDepData has been required and defined in webkit-dep.js + webkitDepData.type = 'chord'; + webkitDepData.ribbonType = false; + for (var i = 0; i < webkitDepData.nodes.length; i++) { + webkitDepData.nodes[i].value = null; + } + for (var i = 0; i < webkitDepData.links.length; i++) { + webkitDepData.links[i].weight = 1; + } + webkitDepData.minRadius = 2; + webkitDepData.maxRadius = 10; + webkitDepData.itemStyle = { + normal: { + label: { + show: true, + rotate: true + }, + chordStyle: { + opacity: 0.2 + } + } + }; + return [webkitDepData]; + } else { + return []; + } + })() +}; + </textarea> + </div><!--/.well --> + </div><!--/span--> + <div id="graphic" class="col-md-11"> + <div id="main" class="main" style="height:600px;"></div> + <div> + <button type="button" class="btn btn-sm btn-success" onclick="refresh(true)">刷 新</button> + <span class="text-primary">切换主题</span> + <select id="theme-select"></select> + + <span id='wrong-message' style="color:red"></span> + </div> + </div><!--/span--> + </div><!--/row--> + + </div><!--/.fluid-container--> + + <footer id="footer"></footer> + <!-- Le javascript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="../asset/js/jquery.min.js"></script> + <script type="text/javascript" src="../asset/js/echartsHome.js"></script> + <script src="../asset/js/bootstrap.min.js"></script> + <script type="text/javascript"> + var webkitDepData; + require(['webkit-dep'], function (wd) { + webkitDepData = wd; + //webkitDepData has been required and defined in webkit-dep.js + webkitDepData.minRadius = 5; + webkitDepData.maxRadius = 8; + webkitDepData.density = 1.1; + webkitDepData.attractiveness = 1.1; + webkitDepData.itemStyle = { + normal : { + linkStyle : { + opacity : 0.5 + } + } + } + // Echarts have been loaded + if (typeof(echarts) !== 'undefined') { + refresh(); + } + }) + </script> + <script src="../asset/js/echartsExample.js"></script> +</body> +</html> diff --git a/src/chart/chord.js b/src/chart/chord.js index 6197163dee..7ed5154d61 100644 --- a/src/chart/chord.js +++ b/src/chart/chord.js @@ -105,6 +105,15 @@ define(function (require) { 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];; + }, + _buildChords: function (series) { var graphs = []; var mainSerie = series[0]; @@ -115,11 +124,11 @@ define(function (require) { var graph; if (serie.data && serie.matrix) { graph = this._getSerieGraphFromDataMatrix( - serie, mainSerie.ribbonType + serie, mainSerie ); } else if (serie.nodes && serie.links) { graph = this._getSerieGraphFromNodeLinks( - serie, mainSerie.ribbonType + serie, mainSerie ); } // 过滤输出为0的节点 @@ -146,7 +155,7 @@ define(function (require) { }); var multiplier = (maxRadius - minRadius) / (max - min); mainGraph.eachNode(function (node) { - var queryTarget = [node, mainSerie]; + var queryTarget = this._getNodeQueryTarget(mainSerie, node); var symbolSize = this.query(queryTarget, 'symbolSize'); if (max === min) { node.layout.size = symbolSize || min; @@ -206,7 +215,7 @@ define(function (require) { this._initHoverHandler(series, graphs); }, - _getSerieGraphFromDataMatrix: function (serie, ribbonType) { + _getSerieGraphFromDataMatrix: function (serie, mainSerie) { var nodesData = []; var count = 0; var matrix = []; @@ -226,8 +235,12 @@ define(function (require) { node[key] = group[key]; } } - this.selectedMap[group.name] = this.isSelected(group.name); - if (this.selectedMap[group.name]) { + // 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++; } @@ -258,7 +271,7 @@ define(function (require) { return graph; }, - _getSerieGraphFromNodeLinks: function (serie, ribbonType) { + _getSerieGraphFromNodeLinks: function (serie, mainSerie) { var graph = new Graph(true); for (var i = 0, len = serie.nodes.length; i < len; i++) { @@ -266,8 +279,12 @@ define(function (require) { if (!n || n.ignore) { continue; } - this.selectedMap[n.name] = this.isSelected(n.name); - if (this.selectedMap[n.name]) { + // 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; } @@ -297,9 +314,9 @@ define(function (require) { graph.eachNode(function (n) { var value = n.data.value; - if (!value) { + if (value == null) { // value 是 null 或者 undefined value = 0; - if (ribbonType) { + if (mainSerie) { // 默认使用所有出边值的和作为节点的大小, 不修改 data 里的数值 for (var i = 0; i < n.outEdges.length; i++) { value += n.outEdges[i].data.weight || 0; @@ -318,7 +335,8 @@ define(function (require) { }); graph.eachEdge(function (e) { e.layout = { - weight: e.data.weight + // 默认 weight 为1 + weight: e.data.weight == null ? 1 : e.data.weight, }; }); @@ -341,7 +359,10 @@ define(function (require) { }); for (var i = 0; i < graphs.length; i++) { graphs[i].eachEdge(function (e) { - e.shape.style.opacity = 0.05; + var queryTarget = [e.data, mainSerie]; + e.shape.style.opacity = self.deepQuery( + queryTarget, 'itemStyle.normal.chordStyle.opacity' + ) * 0.1; e.shape.modSelf(); }); } @@ -405,6 +426,10 @@ define(function (require) { 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({ @@ -477,7 +502,13 @@ define(function (require) { var angle = (startAngle + endAngle) / 2; var x = r * Math.cos(angle); var y = r * Math.sin(angle); - var queryTarget = [node.data, mainSerie]; + var queryTarget = this._getNodeQueryTarget(mainSerie, node.data); + + var category = this._getNodeCategory(mainSerie, node.data); + var color = this.deepQuery(queryTarget, 'itemStyle.normal.color'); + if (!color) { + color = category ? this.getColor(category.name) : this.getColor(node.id); + } var iconShape = new IconShape({ zlevel: this.getZlevelBase(), z: 1, @@ -487,7 +518,7 @@ define(function (require) { width: node.layout.size * 2, height: node.layout.size * 2, iconType: this.deepQuery(queryTarget, 'symbol'), - color: this.deepQuery(queryTarget, 'itemStyle.normal.color') || this.getColor(node.id), + color: color, lineWidth: this.deepQuery(queryTarget, 'itemStyle.normal.borderWidth'), strokeColor: this.deepQuery(queryTarget, 'itemStyle.normal.borderColor') }, diff --git a/src/chart/force.js b/src/chart/force.js index 1858f2fc49..b949f33f2b 100644 --- a/src/chart/force.js +++ b/src/chart/force.js @@ -342,6 +342,13 @@ define(function (require) { zrUtil.merge(shape.highlightStyle, shapeEmphasisStyle[k], true); } } + // 兼容原有写法 + shape.style.strokeColor = shape.style.strokeColor || shape.style.borderColor; + shape.style.lineWidth = shape.style.lineWidth || shape.style.borderWidth; + shape.highlightStyle.strokeColor = + shape.highlightStyle.strokeColor || shape.highlightStyle.borderColor; + shape.highlightStyle.lineWidth = + shape.highlightStyle.lineWidth || shape.highlightStyle.borderWidth; // 节点标签样式 if (this.deepQuery(queryTarget, 'itemStyle.normal.label.show')) { @@ -453,6 +460,17 @@ define(function (require) { } } + // 兼容原有写法 + linkShape.style.lineWidth + = linkShape.style.lineWidth || linkShape.style.width; + linkShape.style.strokeColor + = linkShape.style.strokeColor || linkShape.style.color; + linkShape.highlightStyle.lineWidth + = linkShape.highlightStyle.lineWidth || linkShape.highlightStyle.width; + linkShape.highlightStyle.strokeColor + = linkShape.highlightStyle.strokeColor || linkShape.highlightStyle.color; + + ecData.pack( linkShape, // serie diff --git a/src/component/legend.js b/src/component/legend.js index e807b63ec7..d4798b5109 100644 --- a/src/component/legend.js +++ b/src/component/legend.js @@ -489,9 +489,8 @@ define(function (require) { || series[i].type === ecConfig.CHART_TYPE_FORCE || series[i].type === ecConfig.CHART_TYPE_FUNNEL ) { - data = series[i].type != ecConfig.CHART_TYPE_FORCE - ? (series[i].data || series[i].nodes) // 饼图、雷达图、和弦图得查找里面的数据名字 - : series[i].categories; // 力导布局查找categories配置 + data = series[i].categories || series[i].data || series[i].nodes; + for (var j = 0, k = data.length; j < k; j++) { if (data[j].name === name) { return { diff --git a/src/config.js b/src/config.js index 2b5d531314..37902ee757 100644 --- a/src/config.js +++ b/src/config.js @@ -883,11 +883,12 @@ define(function() { nodeStyle: { brushType: 'both', color: '#f08c2e', - strokeColor: '#5182ab', - lineWidth: 1 + borderColor: '#5182ab', + borderWidth: 1 }, linkStyle: { - strokeColor: '#5182ab' + color: '#5182ab', + width: 1 } }, emphasis: { @@ -947,6 +948,14 @@ define(function() { showScaleText: false, /***************** 上面的配置项在 ribbonType 为 true 时有效 */ + // 分类里如果有样式会覆盖节点默认样式 + // categories: [{ + // itemStyle + // symbol + // symbolSize + // name + // }], + itemStyle: { normal: { borderWidth: 0, @@ -980,6 +989,8 @@ define(function() { } } }, + /****** 使用 Data-matrix 表示数据 */ + // data: [], // Source data matrix /** * target @@ -995,7 +1006,12 @@ define(function() { * * Row based */ - matrix: [] + // matrix: [], + + /****** 使用 node-links 表示数据 */ + // 参考 force + // nodes: [], + // links: [] }, gauge: {