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: {