legend.js 35.1 KB
Newer Older
K
kener 已提交
1 2 3 4 5 6 7 8
/**
 * echarts组件:图例
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, linzhifeng@baidu.com)
 *
 */
define(function (require) {
K
kener 已提交
9 10 11
    var Base = require('./base');
    
    // 图形依赖
K
kener 已提交
12 13
    var TextShape = require('zrender/shape/Text');
    var RectangleShape = require('zrender/shape/Rectangle');
K
kener 已提交
14
    var SectorShape = require('zrender/shape/Sector');
K
kener 已提交
15
    //var BeziercurveShape = require('zrender/shape/Beziercurve');
K
kener 已提交
16
    var IconShape = require('../util/shape/Icon');
K
kener 已提交
17
    var CandleShape = require('../util/shape/Candle');
K
kener 已提交
18
    
K
kener 已提交
19 20 21 22
    var ecConfig = require('../config');
    var zrUtil = require('zrender/tool/util');
    var zrArea = require('zrender/tool/area');

K
kener 已提交
23 24 25 26 27 28
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 图表参数
     */
K
kener 已提交
29 30
    function Legend(ecTheme, messageCenter, zr, option, myChart) {
        if (!this.query(option, 'legend.data')) {
K
jshint  
kener 已提交
31
            console.error('option.legend.data has not been defined.');
K
kener 已提交
32 33 34 35
            return;
        }
        
        Base.call(this, ecTheme, messageCenter, zr, option, myChart);
K
kener 已提交
36
        
K
jshint  
kener 已提交
37 38 39 40 41
        var self = this;
        self._legendSelected = function (param) {
            self.__legendSelected(param);
        };
        
K
kener 已提交
42 43 44 45 46
        this._colorIndex = 0;
        this._colorMap = {};
        this._selectedMap = {};
        
        this.refresh(option);
K
kener 已提交
47 48 49 50 51
    }
    
    Legend.prototype = {
        type : ecConfig.COMPONENT_TYPE_LEGEND,
        _buildShape : function () {
K
kener 已提交
52
            // 图例元素组的位置参数,通过计算所得x, y, width, height
K
kener 已提交
53
            this._itemGroupLocation = this._getItemGroupLocation();
K
kener 已提交
54

K
kener 已提交
55 56
            this._buildBackground();
            this._buildItem();
K
kener 已提交
57

K
kener 已提交
58 59
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                this.zr.addShape(this.shapeList[i]);
K
kener 已提交
60
            }
K
kener 已提交
61
        },
K
kener 已提交
62 63 64 65

        /**
         * 构建所有图例元素
         */
K
kener 已提交
66 67
        _buildItem : function () {
            var data = this.legendOption.data;
K
kener 已提交
68 69 70 71 72
            var dataLength = data.length;
            var itemName;
            var itemType;
            var itemShape;
            var textShape;
K
kener 已提交
73
            var textStyle  = this.legendOption.textStyle;
74 75
            var dataTextStyle;
            var dataFont;
K
kener 已提交
76

K
kener 已提交
77 78 79 80 81 82 83
            var zrWidth = this.zr.getWidth();
            var zrHeight = this.zr.getHeight();
            var lastX = this._itemGroupLocation.x;
            var lastY = this._itemGroupLocation.y;
            var itemWidth = this.legendOption.itemWidth;
            var itemHeight = this.legendOption.itemHeight;
            var itemGap = this.legendOption.itemGap;
K
kener 已提交
84 85
            var color;

K
kener 已提交
86
            if (this.legendOption.orient == 'vertical' && this.legendOption.x == 'right') {
K
kener 已提交
87 88
                lastX = this._itemGroupLocation.x
                        + this._itemGroupLocation.width
K
kener 已提交
89 90 91 92
                        - itemWidth;
            }

            for (var i = 0; i < dataLength; i++) {
93 94
                dataTextStyle = zrUtil.merge(
                    data[i].textStyle || {},
K
kener 已提交
95
                    textStyle
96
                );
K
kener 已提交
97
                dataFont = this.getFont(dataTextStyle);
98
                
K
kener 已提交
99
                itemName = this._getName(data[i]);
K
kener 已提交
100
                if (itemName === '') {
K
kener 已提交
101 102
                    if (this.legendOption.orient == 'horizontal') {
                        lastX = this._itemGroupLocation.x;
K
kener 已提交
103 104 105
                        lastY += itemHeight + itemGap;
                    }
                    else {
K
kener 已提交
106
                        this.legendOption.x == 'right'
K
kener 已提交
107 108
                            ? lastX -= this._itemGroupLocation.maxWidth + itemGap
                            : lastX += this._itemGroupLocation.maxWidth + itemGap;
K
kener 已提交
109
                        lastY = this._itemGroupLocation.y;
K
kener 已提交
110 111 112
                    }
                    continue;
                }
K
kener 已提交
113
                itemType = data[i].icon || this._getSomethingByName(itemName).type;
K
kener 已提交
114
                
K
kener 已提交
115
                color = this.getColor(itemName);
K
kener 已提交
116

K
kener 已提交
117
                if (this.legendOption.orient == 'horizontal') {
K
kener 已提交
118
                    if (zrWidth - lastX < 200   // 最后200px做分行预判
K
kener 已提交
119
                        && (itemWidth + 5 + zrArea.getTextWidth(itemName, dataFont)
K
kener 已提交
120
                            // 分行的最后一个不用算itemGap
K
kener 已提交
121 122
                            + (i == dataLength - 1 || data[i+1] === '' ? 0 : itemGap)
                           ) >= zrWidth - lastX
K
kener 已提交
123
                    ) {
K
kener 已提交
124
                        lastX = this._itemGroupLocation.x;
K
kener 已提交
125 126 127
                        lastY += itemHeight + itemGap;
                    }
                }
K
kener 已提交
128 129 130 131
                else {
                    if (zrHeight - lastY < 200   // 最后200px做分行预判
                        && (itemHeight
                            // 分行的最后一个不用算itemGap
K
kener 已提交
132 133
                            + (i == dataLength - 1 || data[i+1] === '' ? 0 : itemGap)
                           ) >= zrHeight - lastY
K
kener 已提交
134
                    ) {
K
kener 已提交
135 136 137 138
                        this.legendOption.x == 'right'
                        ? lastX -= this._itemGroupLocation.maxWidth + itemGap
                        : lastX += this._itemGroupLocation.maxWidth + itemGap;
                        lastY = this._itemGroupLocation.y;
K
kener 已提交
139 140
                    }
                }
K
kener 已提交
141 142

                // 图形
K
kener 已提交
143
                itemShape = this._getItemShapeByType(
K
kener 已提交
144 145
                    lastX, lastY,
                    itemWidth, itemHeight,
K
kener 已提交
146
                    (this._selectedMap[itemName] ? color : '#ccc'),
147 148
                    itemType,
                    color
K
kener 已提交
149 150
                );
                itemShape._name = itemName;
K
kener 已提交
151
                itemShape = new IconShape(itemShape);
K
kener 已提交
152 153 154

                // 文字
                textShape = {
K
kener 已提交
155
                    // shape : 'text',
K
kener 已提交
156
                    zlevel : this._zlevelBase,
K
kener 已提交
157 158
                    style : {
                        x : lastX + itemWidth + 5,
K
kener 已提交
159
                        y : lastY + itemHeight / 2,
K
kener 已提交
160
                        color : this._selectedMap[itemName]
161
                                ? (dataTextStyle.color === 'auto' ? color : dataTextStyle.color)
K
kener 已提交
162 163
                                : '#ccc',
                        text: itemName,
164
                        textFont: dataFont,
K
kener 已提交
165
                        textBaseline: 'middle'
K
kener 已提交
166
                    },
167 168 169 170
                    highlightStyle : {
                        color : color,
                        brushType: 'fill'
                    },
K
kener 已提交
171 172
                    hoverable : !!this.legendOption.selectedMode,
                    clickable : !!this.legendOption.selectedMode
K
kener 已提交
173 174
                };

K
kener 已提交
175 176
                if (this.legendOption.orient == 'vertical'
                    && this.legendOption.x == 'right'
K
kener 已提交
177 178 179 180 181 182
                ) {
                    textShape.style.x -= (itemWidth + 10);
                    textShape.style.textAlign = 'right';
                }

                textShape._name = itemName;
K
kener 已提交
183 184
                textShape = new TextShape(textShape);
                
K
kener 已提交
185
                if (this.legendOption.selectedMode) {
K
jshint  
kener 已提交
186
                    itemShape.onclick = textShape.onclick = this._legendSelected;
K
kener 已提交
187 188 189
                    itemShape.onmouseover =  textShape.onmouseover = this.hoverConnect;
                    itemShape.hoverConnect = textShape.id;
                    textShape.hoverConnect = itemShape.id;
190
                }
K
kener 已提交
191 192
                this.shapeList.push(itemShape);
                this.shapeList.push(textShape);
K
kener 已提交
193

K
kener 已提交
194
                if (this.legendOption.orient == 'horizontal') {
K
kener 已提交
195
                    lastX += itemWidth + 5
196
                             + zrArea.getTextWidth(itemName, dataFont)
K
kener 已提交
197 198 199 200 201 202
                             + itemGap;
                }
                else {
                    lastY += itemHeight + itemGap;
                }
            }
K
kener 已提交
203
        
K
kener 已提交
204 205 206
            if (this.legendOption.orient == 'horizontal'
                && this.legendOption.x == 'center'
                && lastY != this._itemGroupLocation.y
K
kener 已提交
207 208
            ) {
                // 多行橫排居中优化
K
kener 已提交
209
                this._mLineOptimize();
K
kener 已提交
210
            }
K
kener 已提交
211
        },
K
kener 已提交
212
        
K
kener 已提交
213 214 215 216
        _getName : function(data) {
            return typeof data.name != 'undefined' ? data.name : data;
        },
        
K
kener 已提交
217
        // 多行橫排居中优化
K
kener 已提交
218
        _mLineOptimize : function () {
K
kener 已提交
219
            var lineOffsetArray = []; // 每行宽度
K
kener 已提交
220 221 222
            var lastX = this._itemGroupLocation.x;
            for (var i = 2, l = this.shapeList.length; i < l; i++) {
                if (this.shapeList[i].style.x == lastX) {
K
kener 已提交
223 224
                    lineOffsetArray.push(
                        (
K
kener 已提交
225
                            this._itemGroupLocation.width 
K
kener 已提交
226
                            - (
K
kener 已提交
227
                                this.shapeList[i - 1].style.x
K
kener 已提交
228
                                + zrArea.getTextWidth(
K
kener 已提交
229 230
                                      this.shapeList[i - 1].style.text,
                                      this.shapeList[i - 1].style.textFont
K
kener 已提交
231 232 233 234 235
                                  )
                                - lastX
                            )
                        ) / 2
                    );
K
kener 已提交
236
                }
K
kener 已提交
237 238 239
                else if (i == l - 1) {
                    lineOffsetArray.push(
                        (
K
kener 已提交
240
                            this._itemGroupLocation.width 
K
kener 已提交
241
                            - (
K
kener 已提交
242
                                this.shapeList[i].style.x
K
kener 已提交
243
                                + zrArea.getTextWidth(
K
kener 已提交
244 245
                                      this.shapeList[i].style.text,
                                      this.shapeList[i].style.textFont
K
kener 已提交
246 247 248 249 250 251 252 253
                                  )
                                - lastX
                            )
                        ) / 2
                    );
                }
            }
            var curLineIndex = -1;
K
kener 已提交
254 255
            for (var i = 1, l = this.shapeList.length; i < l; i++) {
                if (this.shapeList[i].style.x == lastX) {
K
kener 已提交
256 257 258 259 260 261
                    curLineIndex++;
                }
                if (lineOffsetArray[curLineIndex] === 0) {
                    continue;
                }
                else {
K
kener 已提交
262
                    this.shapeList[i].style.x += lineOffsetArray[curLineIndex];
K
kener 已提交
263 264
                }
            }
K
kener 已提交
265
        },
K
kener 已提交
266

K
kener 已提交
267 268 269 270 271
        _buildBackground : function () {
            var pTop = this.legendOption.padding[0];
            var pRight = this.legendOption.padding[1];
            var pBottom = this.legendOption.padding[2];
            var pLeft = this.legendOption.padding[3];
K
kener 已提交
272

K
kener 已提交
273 274
            this.shapeList.push(new RectangleShape({
                zlevel : this._zlevelBase,
K
kener 已提交
275 276
                hoverable :false,
                style : {
K
kener 已提交
277 278 279 280
                    x : this._itemGroupLocation.x - pLeft,
                    y : this._itemGroupLocation.y - pTop,
                    width : this._itemGroupLocation.width + pLeft + pRight,
                    height : this._itemGroupLocation.height + pTop + pBottom,
K
kener 已提交
281
                    brushType : this.legendOption.borderWidth === 0 ? 'fill' : 'both',
K
kener 已提交
282 283 284
                    color : this.legendOption.backgroundColor,
                    strokeColor : this.legendOption.borderColor,
                    lineWidth : this.legendOption.borderWidth
K
kener 已提交
285
                }
K
kener 已提交
286
            }));
K
kener 已提交
287
        },
K
kener 已提交
288 289 290 291

        /**
         * 根据选项计算图例实体的位置坐标
         */
K
kener 已提交
292 293
        _getItemGroupLocation : function () {
            var data = this.legendOption.data;
K
kener 已提交
294
            var dataLength = data.length;
K
kener 已提交
295 296 297 298 299
            var itemGap = this.legendOption.itemGap;
            var itemWidth = this.legendOption.itemWidth + 5; // 5px是图形和文字的间隔,不可配
            var itemHeight = this.legendOption.itemHeight;
            var textStyle  = this.legendOption.textStyle;
            var font = this.getFont(textStyle);
K
kener 已提交
300 301
            var totalWidth = 0;
            var totalHeight = 0;
K
kener 已提交
302 303 304
            var padding = this.legendOption.padding;
            var zrWidth = this.zr.getWidth() - padding[1] - padding[3];
            var zrHeight = this.zr.getHeight() - padding[0] - padding[2];
K
kener 已提交
305 306 307
            
            var temp = 0; // 宽高计算,用于多行判断
            var maxWidth = 0; // 垂直布局有用
K
kener 已提交
308
            if (this.legendOption.orient == 'horizontal') {
K
kener 已提交
309
                // 水平布局,计算总宽度
K
kener 已提交
310
                totalHeight = itemHeight;
K
kener 已提交
311
                for (var i = 0; i < dataLength; i++) {
K
kener 已提交
312
                    if (this._getName(data[i]) === '') {
K
kener 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326
                        temp -= itemGap;
                        if (temp > zrWidth) {
                            totalWidth = zrWidth;
                            totalHeight += itemHeight + itemGap;
                        }
                        else {
                            totalWidth = Math.max(totalWidth, temp);
                        }
                        totalHeight += itemHeight + itemGap;
                        temp = 0;
                        continue;
                    }
                    temp += itemWidth
                            + zrArea.getTextWidth(
K
kener 已提交
327
                                  this._getName(data[i]),
328
                                  data[i].textStyle 
K
kener 已提交
329
                                  ? this.getFont(zrUtil.merge(
330
                                        data[i].textStyle || {},
K
kener 已提交
331
                                        textStyle
332 333
                                    ))
                                  : font
K
kener 已提交
334 335 336 337 338 339 340 341 342 343
                              )
                            + itemGap;
                }
                totalHeight = Math.max(totalHeight, itemHeight);
                temp -= itemGap;    // 减去最后一个的itemGap
                if (temp > zrWidth) {
                    totalWidth = zrWidth;
                    totalHeight += itemHeight + itemGap;
                } else {
                    totalWidth = Math.max(totalWidth, temp);
K
kener 已提交
344 345 346 347 348 349 350 351
                }
            }
            else {
                // 垂直布局,计算总高度
                for (var i = 0; i < dataLength; i++) {
                    maxWidth = Math.max(
                        maxWidth,
                        zrArea.getTextWidth(
K
kener 已提交
352
                            this._getName(data[i]),
353
                            data[i].textStyle 
K
kener 已提交
354
                            ? this.getFont(zrUtil.merge(
355
                                  data[i].textStyle || {},
K
kener 已提交
356
                                  textStyle
357 358
                              ))
                            : font
K
kener 已提交
359 360 361
                        )
                    );
                }
K
kener 已提交
362 363 364
                maxWidth += itemWidth;
                totalWidth = maxWidth;
                for (var i = 0; i < dataLength; i++) {
K
kener 已提交
365
                    if (this._getName(data[i]) === '') {
K
kener 已提交
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
                        temp -= itemGap;
                        if (temp > zrHeight) {
                            totalHeight = zrHeight;
                            totalWidth += maxWidth + itemGap;
                        }
                        else {
                            totalHeight = Math.max(totalHeight, temp);
                        }
                        totalWidth += maxWidth + itemGap;
                        temp = 0;
                        continue;
                    }
                    temp += itemHeight + itemGap;
                }
                totalWidth = Math.max(totalWidth, maxWidth);
                temp -= itemGap;    // 减去最后一个的itemGap
                if (temp > zrHeight) {
                    totalHeight = zrHeight;
                    totalWidth += maxWidth + itemGap;
                } else {
                    totalHeight = Math.max(totalHeight, temp);
                }
K
kener 已提交
388 389
            }

K
kener 已提交
390 391
            zrWidth = this.zr.getWidth();
            zrHeight = this.zr.getHeight();
K
kener 已提交
392
            var x;
K
kener 已提交
393
            switch (this.legendOption.x) {
K
kener 已提交
394 395 396 397
                case 'center' :
                    x = Math.floor((zrWidth - totalWidth) / 2);
                    break;
                case 'left' :
K
kener 已提交
398
                    x = this.legendOption.padding[3] + this.legendOption.borderWidth;
K
kener 已提交
399 400 401 402
                    break;
                case 'right' :
                    x = zrWidth
                        - totalWidth
K
kener 已提交
403 404 405
                        - this.legendOption.padding[1]
                        - this.legendOption.padding[3]
                        - this.legendOption.borderWidth * 2;
K
kener 已提交
406 407
                    break;
                default :
K
kener 已提交
408
                    x = this.parsePercent(this.legendOption.x, zrWidth);
K
kener 已提交
409 410
                    break;
            }
K
kener 已提交
411
            
K
kener 已提交
412
            var y;
K
kener 已提交
413
            switch (this.legendOption.y) {
K
kener 已提交
414
                case 'top' :
K
kener 已提交
415
                    y = this.legendOption.padding[0] + this.legendOption.borderWidth;
K
kener 已提交
416 417 418 419
                    break;
                case 'bottom' :
                    y = zrHeight
                        - totalHeight
K
kener 已提交
420 421 422
                        - this.legendOption.padding[0]
                        - this.legendOption.padding[2]
                        - this.legendOption.borderWidth * 2;
K
kener 已提交
423 424 425 426 427
                    break;
                case 'center' :
                    y = Math.floor((zrHeight - totalHeight) / 2);
                    break;
                default :
K
kener 已提交
428
                    y = this.parsePercent(this.legendOption.y, zrHeight);
K
kener 已提交
429 430 431 432 433 434 435
                    break;
            }

            return {
                x : x,
                y : y,
                width : totalWidth,
K
kener 已提交
436 437
                height : totalHeight,
                maxWidth : maxWidth
K
kener 已提交
438
            };
K
kener 已提交
439
        },
K
kener 已提交
440 441

        /**
K
kener 已提交
442
         * 根据名称返回series数据或data
K
kener 已提交
443
         */
K
kener 已提交
444 445
        _getSomethingByName : function (name) {
            var series = this.option.series;
K
kener 已提交
446
            var data;
K
kener 已提交
447 448 449
            for (var i = 0, l = series.length; i < l; i++) {
                if (series[i].name == name) {
                    // 系列名称优先
K
kener 已提交
450 451 452 453 454 455
                    return {
                        type : series[i].type,
                        series : series[i],
                        seriesIndex : i,
                        data : null,
                        dataIndex : -1
K
kener 已提交
456
                    };
K
kener 已提交
457 458
                }

K
kener 已提交
459 460 461
                if (
                    series[i].type == ecConfig.CHART_TYPE_PIE 
                    || series[i].type == ecConfig.CHART_TYPE_RADAR
L
lang 已提交
462
                    || series[i].type == ecConfig.CHART_TYPE_CHORD
K
kener 已提交
463
                    || series[i].type == ecConfig.CHART_TYPE_FORCE
K
kener 已提交
464
                    || series[i].type == ecConfig.CHART_TYPE_FUNNEL
K
kener 已提交
465
                ) {
K
kener 已提交
466 467 468
                    data = series[i].type != ecConfig.CHART_TYPE_FORCE
                           ? series[i].data         // 饼图、雷达图、和弦图得查找里面的数据名字
                           : series[i].categories;  // 力导布局查找categories配置
K
kener 已提交
469 470
                    for (var j = 0, k = data.length; j < k; j++) {
                        if (data[j].name == name) {
K
kener 已提交
471 472 473 474 475 476
                            return {
                                type : series[i].type,
                                series : series[i],
                                seriesIndex : i,
                                data : data[j],
                                dataIndex : j
K
kener 已提交
477
                            };
K
kener 已提交
478 479
                        }
                    }
K
kener 已提交
480
                }
K
kener 已提交
481
            }
K
kener 已提交
482 483 484 485 486 487
            return {
                type : 'bar',
                series : null,
                seriesIndex : -1,
                data : null,
                dataIndex : -1
K
kener 已提交
488
            };
K
kener 已提交
489
        },
K
kener 已提交
490
        
K
kener 已提交
491
        _getItemShapeByType : function (x, y, width, height, color, itemType, defaultColor) {
K
kener 已提交
492
            var highlightColor = color === '#ccc' ? defaultColor : color;
493
            var itemShape = {
K
kener 已提交
494
                zlevel : this._zlevelBase,
495
                style : {
K
kener 已提交
496
                    iconType : 'legendicon' + itemType,
497 498 499 500 501 502
                    x : x,
                    y : y,
                    width : width,
                    height : height,
                    color : color,
                    strokeColor : color,
503 504 505 506 507 508
                    lineWidth : 2
                },
                highlightStyle: {
                    color : highlightColor,
                    strokeColor : highlightColor,
                    lineWidth : 1
509
                },
K
kener 已提交
510 511
                hoverable : this.legendOption.selectedMode,
                clickable : this.legendOption.selectedMode
512
            };
K
kener 已提交
513 514 515 516 517 518 519 520
            
            var imageLocation;
            if (itemType.match('image')) {
                var imageLocation = itemType.replace(
                    new RegExp('^image:\\/\\/'), ''
                );
                itemType = 'image';
            }
521
            // 特殊设置
K
kener 已提交
522 523
            switch (itemType) {
                case 'line' :
524
                    itemShape.style.brushType = 'stroke';
525 526 527 528 529
                    itemShape.highlightStyle.lineWidth = 3;
                    break;
                case 'radar' :
                case 'scatter' :   
                    itemShape.highlightStyle.lineWidth = 3;
530
                    break;
K
kener 已提交
531
                case 'k' :
532
                    itemShape.style.brushType = 'both';
533 534
                    itemShape.highlightStyle.lineWidth = 3;
                    itemShape.highlightStyle.color =
K
kener 已提交
535 536
                    itemShape.style.color = this.query(this.ecTheme, 'k.itemStyle.normal.color') 
                                            || '#fff';
537
                    itemShape.style.strokeColor = color != '#ccc' 
K
kener 已提交
538 539
                        ? (this.query(this.ecTheme, 'k.itemStyle.normal.lineStyle.color') 
                           || '#ff3200')
540
                        : color;
K
kener 已提交
541 542 543 544 545 546 547 548
                    break;
                case 'image' :
                    itemShape.style.iconType = 'image';
                    itemShape.style.image = imageLocation;
                    if (color === '#ccc') {
                        itemShape.style.opacity = 0.5;
                    }
                    break;
K
kener 已提交
549
            }
550
            return itemShape;
K
kener 已提交
551
        },
K
kener 已提交
552

K
jshint  
kener 已提交
553
        __legendSelected : function (param) {
K
kener 已提交
554
            var itemName = param.target._name;
K
kener 已提交
555 556 557
            if (this.legendOption.selectedMode === 'single') {
                for (var k in this._selectedMap) {
                    this._selectedMap[k] = false;
K
kener 已提交
558 559
                }
            }
K
kener 已提交
560 561
            this._selectedMap[itemName] = !this._selectedMap[itemName];
            this.messageCenter.dispatch(
K
kener 已提交
562 563
                ecConfig.EVENT.LEGEND_SELECTED,
                param.event,
K
kener 已提交
564
                {
K
kener 已提交
565
                    selected : this._selectedMap,
K
kener 已提交
566
                    target : itemName
K
kener 已提交
567 568
                },
                this.myChart
K
kener 已提交
569
            );
K
kener 已提交
570
        },
K
kener 已提交
571 572 573 574

        /**
         * 刷新
         */
K
kener 已提交
575 576
        refresh : function (newOption) {
            if (newOption) {
K
kener 已提交
577
                this.option = newOption || this.option;
K
kener 已提交
578
                this.option.legend = this.reformOption(this.option.legend);
K
kener 已提交
579
                // 补全padding属性
K
kener 已提交
580 581
                this.option.legend.padding = this.reformCssArray(
                    this.option.legend.padding
K
kener 已提交
582
                );
K
kener 已提交
583 584 585 586 587 588 589
                this.legendOption = this.option.legend;
                
                var data = this.legendOption.data || [];
                var itemName;
                var something;
                var color;
                var queryTarget;
K
kener 已提交
590 591 592 593 594 595 596
                if (this.legendOption.selected) {
                    for (var k in this.legendOption.selected) {
                        this._selectedMap[k] = typeof this._selectedMap[k] != 'undefined'
                                               ? this._selectedMap[k]
                                               : this.legendOption.selected[k];
                    }
                }
K
kener 已提交
597
                for (var i = 0, dataLength = data.length; i < dataLength; i++) {
K
kener 已提交
598
                    itemName = this._getName(data[i]);
K
kener 已提交
599 600 601 602 603 604 605 606 607 608
                    if (itemName === '') {
                        continue;
                    }
                    something = this._getSomethingByName(itemName);
                    if (!something.series) {
                        this._selectedMap[itemName] = false;
                    } 
                    else {
                        if (something.data
                            && (something.type == ecConfig.CHART_TYPE_PIE
K
kener 已提交
609 610
                                || something.type == ecConfig.CHART_TYPE_FORCE
                                || something.type == ecConfig.CHART_TYPE_FUNNEL)
K
kener 已提交
611 612 613 614 615 616 617 618
                        ) {
                            queryTarget = [something.data, something.series];
                        }
                        else {
                            queryTarget = [something.series];
                        }
                        
                        color = this.getItemStyleColor(
K
kener 已提交
619
                            this.deepQuery(queryTarget, 'itemStyle.normal.color'),
K
kener 已提交
620 621 622 623 624 625 626
                            something.seriesIndex,
                            something.dataIndex,
                            something.data
                        );
                        if (color && something.type != ecConfig.CHART_TYPE_K) {
                            this.setColor(itemName, color);
                        }
K
kener 已提交
627 628 629
                        this._selectedMap[itemName] = 
                            typeof this._selectedMap[itemName] != 'undefined'
                            ? this._selectedMap[itemName] : true; 
K
kener 已提交
630 631
                    }
                }
K
kener 已提交
632
            }
K
kener 已提交
633 634 635
            this.clear();
            this._buildShape();
        },
K
kener 已提交
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
        
        getRelatedAmount : function(name) {
            var amount = 0;
            var series = this.option.series;
            var data;
            for (var i = 0, l = series.length; i < l; i++) {
                if (series[i].name == name) {
                    // 系列名称优先
                    amount++;
                }

                if (
                    series[i].type == ecConfig.CHART_TYPE_PIE 
                    || series[i].type == ecConfig.CHART_TYPE_RADAR
                    || series[i].type == ecConfig.CHART_TYPE_CHORD
                    || 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].categories;  // 力导布局查找categories配置
                    for (var j = 0, k = data.length; j < k; j++) {
                        if (data[j].name == name && data[j].value != '-') {
K
kener 已提交
659
                            amount++;
K
kener 已提交
660 661 662 663 664 665
                        }
                    }
                }
            }
            return amount;
        },
K
kener 已提交
666

K
kener 已提交
667 668 669
        setColor : function (legendName, color) {
            this._colorMap[legendName] = color;
        },
K
kener 已提交
670

K
kener 已提交
671 672 673
        getColor : function (legendName) {
            if (!this._colorMap[legendName]) {
                this._colorMap[legendName] = this.zr.getColor(this._colorIndex++);
K
kener 已提交
674
            }
K
kener 已提交
675 676
            return this._colorMap[legendName];
        },
K
kener 已提交
677
        
K
kener 已提交
678 679 680
        hasColor : function (legendName) {
            return this._colorMap[legendName] ? this._colorMap[legendName] : false;
        },
K
kener 已提交
681

K
kener 已提交
682
        add : function (name, color){
K
kener 已提交
683 684 685 686 687 688 689
            var data = this.legendOption.data;
            for (var i = 0, dataLength = data.length; i < dataLength; i++) {
                if (this._getName(data[i]) == name) {
                    // 已有就不重复加了
                    return;
                }
            }
K
kener 已提交
690 691 692 693
            this.legendOption.data.push(name);
            this.setColor(name,color);
            this._selectedMap[name] = true;
        },
K
kener 已提交
694

K
kener 已提交
695 696
        del : function (name){
            var data = this.legendOption.data;
K
kener 已提交
697
            for (var i = 0, dataLength = data.length; i < dataLength; i++) {
K
kener 已提交
698 699
                if (this._getName(data[i]) == name) {
                    return this.legendOption.data.splice(i, 1);
K
kener 已提交
700 701
                }
            }
K
kener 已提交
702
        },
703 704 705 706 707 708
        
        /**
         * 特殊图形元素回调设置
         * @param {Object} name
         * @param {Object} itemShape
         */
K
kener 已提交
709
        getItemShape : function (name) {
K
kener 已提交
710 711 712
            if (typeof name == 'undefined') {
                return;
            }
713
            var shape;
K
kener 已提交
714 715
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                shape = this.shapeList[i];
K
kener 已提交
716
                if (shape._name == name && shape.type != 'text') {
717 718 719
                    return shape;
                }
            }
K
kener 已提交
720
        },
721 722 723 724 725 726
        
        /**
         * 特殊图形元素回调设置
         * @param {Object} name
         * @param {Object} itemShape
         */
K
kener 已提交
727
        setItemShape : function (name, itemShape) {
728
            var shape;
K
kener 已提交
729 730
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                shape = this.shapeList[i];
K
kener 已提交
731
                if (shape._name == name && shape.type != 'text') {
K
kener 已提交
732
                    if (!this._selectedMap[name]) {
733 734 735
                        itemShape.style.color = '#ccc';
                        itemShape.style.strokeColor = '#ccc';
                    }
K
kener 已提交
736
                    this.zr.modShape(shape.id, itemShape);
737 738
                }
            }
K
kener 已提交
739
        },
K
kener 已提交
740

K
kener 已提交
741 742 743
        isSelected : function (itemName) {
            if (typeof this._selectedMap[itemName] != 'undefined') {
                return this._selectedMap[itemName];
K
kener 已提交
744 745 746 747 748
            }
            else {
                // 没在legend里定义的都为true啊~
                return true;
            }
K
kener 已提交
749
        },
K
kener 已提交
750
        
K
kener 已提交
751 752 753
        getSelectedMap : function () {
            return this._selectedMap;
        },
K
kener 已提交
754
        
K
kener 已提交
755 756 757 758 759 760 761 762 763
        setSelected : function(itemName, selectStatus) {
            if (this.legendOption.selectedMode === 'single') {
                for (var k in this._selectedMap) {
                    this._selectedMap[k] = false;
                }
            }
            this._selectedMap[itemName] = selectStatus;
            this.messageCenter.dispatch(
                ecConfig.EVENT.LEGEND_SELECTED,
K
kener 已提交
764
                null,
K
kener 已提交
765 766 767
                {
                    selected : this._selectedMap,
                    target : itemName
K
kener 已提交
768 769
                },
                this.myChart
K
kener 已提交
770 771 772
            );
        },
        
K
kener 已提交
773 774 775
        /**
         * 图例选择
         */
K
kener 已提交
776
        onlegendSelected : function (param, status) {
K
kener 已提交
777
            var legendSelected = param.selected;
K
kener 已提交
778
            for (var itemName in legendSelected) {
K
kener 已提交
779
                if (this._selectedMap[itemName] != legendSelected[itemName]) {
K
kener 已提交
780 781 782
                    // 有一项不一致都需要重绘
                    status.needRefresh = true;
                }
K
kener 已提交
783
                this._selectedMap[itemName] = legendSelected[itemName];
K
kener 已提交
784 785 786
            }
            return;
        }
K
jshint  
kener 已提交
787
    };
788 789 790 791 792 793 794
    
    var legendIcon = {
        line : function (ctx, style) {
            var dy = style.height / 2;
            ctx.moveTo(style.x,     style.y + dy);
            ctx.lineTo(style.x + style.width,style.y + dy);
        },
K
kener 已提交
795
        
796 797 798 799 800
        pie : function (ctx, style) {
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
K
kener 已提交
801
            SectorShape.prototype.buildPath(ctx, {
802 803 804 805 806 807 808
                x : x + width / 2,
                y : y + height + 2,
                r : height + 2,
                r0 : 6,
                startAngle : 45,
                endAngle : 135
            });
K
kener 已提交
809
        },
K
kener 已提交
810
        /*
K
kener 已提交
811
        chord : function (ctx, style) {
K
kener 已提交
812 813 814 815 816
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
            ctx.moveTo(x, y + height);
K
kener 已提交
817
            BeziercurveShape.prototype.buildPath(ctx, {
K
kener 已提交
818 819 820 821 822 823 824
                xStart : x,
                yStart : y + height,
                cpX1 : x + width,
                cpY1 : y + height,
                cpX2 : x,
                cpY2 : y + 4,
                xEnd : x + width,
K
,号  
kener 已提交
825
                yEnd : y + 4
K
kener 已提交
826 827
            });
            ctx.lineTo(x + width, y);
K
kener 已提交
828
            BeziercurveShape.prototype.buildPath(ctx, {
K
kener 已提交
829 830 831 832 833 834 835
                xStart : x + width,
                yStart : y,
                cpX1 : x,
                cpY1 : y,
                cpX2 : x + width,
                cpY2 : y + height - 4,
                xEnd : x,
K
,号  
kener 已提交
836
                yEnd : y + height - 4
K
kener 已提交
837 838 839
            });
            ctx.lineTo(x, y + height);
        },
K
kener 已提交
840
        */
841 842 843 844 845
        k : function (ctx, style) {
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
K
kener 已提交
846
            CandleShape.prototype.buildPath(ctx, {
847 848 849 850 851
                x : x + width / 2,
                y : [y + 1, y + 1, y + height - 6, y + height],
                width : width - 6
            });
        },
K
kener 已提交
852
        
853
        bar : function (ctx, style) {
K
kener 已提交
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
            var x = style.x;
            var y = style.y +1;
            var width = style.width;
            var height = style.height - 2;
            var r = 3;
            
            ctx.moveTo(x + r, y);
            ctx.lineTo(x + width - r, y);
            ctx.quadraticCurveTo(
                x + width, y, x + width, y + r
            );
            ctx.lineTo(x + width, y + height - r);
            ctx.quadraticCurveTo(
                x + width, y + height, x + width - r, y + height
            );
            ctx.lineTo(x + r, y + height);
            ctx.quadraticCurveTo(
                x, y + height, x, y + height - r
            );
            ctx.lineTo(x, y + r);
            ctx.quadraticCurveTo(x, y, x + r, y);
K
kener 已提交
875
        },
K
kener 已提交
876
        
K
kener 已提交
877
        force : function (ctx, style) {
K
kener 已提交
878
            IconShape.prototype.iconLibrary.circle(ctx, style);
K
kener 已提交
879
        },
K
kener 已提交
880
        
K
kener 已提交
881
        radar: function (ctx, style) {
K
kener 已提交
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
            var n = 6;
            var x = style.x + style.width / 2;
            var y = style.y + style.height / 2;
            var r = style.height / 2;

            var dStep = 2 * Math.PI / n;
            var deg = -Math.PI / 2;
            var xStart = x + r * Math.cos(deg);
            var yStart = y + r * Math.sin(deg);
            
            ctx.moveTo(xStart, yStart);
            deg += dStep;
            for (var i = 0, end = n - 1; i < end; i ++) {
                ctx.lineTo(x + r * Math.cos(deg), y + r * Math.sin(deg));
                deg += dStep;
            }
            ctx.lineTo(xStart, yStart);
899
        }
K
kener 已提交
900
    };
K
kener 已提交
901 902
    legendIcon.chord = legendIcon.pie;
    legendIcon.map = legendIcon.bar;
903
    
K
kener 已提交
904 905 906 907
    for (var k in legendIcon) {
        IconShape.prototype.iconLibrary['legendicon' + k] = legendIcon[k];
    }
    
K
kener 已提交
908 909
    zrUtil.inherits(Legend, Base);
    
910 911
    require('../component').define('legend', Legend);
    
K
kener 已提交
912 913 914 915
    return Legend;
});