legend.js 35.9 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
        var self = this;
        self._legendSelected = function (param) {
            self.__legendSelected(param);
        };
K
kener 已提交
41 42 43
        self._dispatchHoverLink = function(param) {
            return self.__dispatchHoverLink(param);
        };
K
jshint  
kener 已提交
44
        
K
kener 已提交
45 46 47 48 49
        this._colorIndex = 0;
        this._colorMap = {};
        this._selectedMap = {};
        
        this.refresh(option);
K
kener 已提交
50 51 52
    }
    
    Legend.prototype = {
53 54
        type: ecConfig.COMPONENT_TYPE_LEGEND,
        _buildShape: function () {
K
kener 已提交
55 56 57
            if (!this.legendOption.show) {
                return;
            }
K
kener 已提交
58
            // 图例元素组的位置参数,通过计算所得x, y, width, height
K
kener 已提交
59
            this._itemGroupLocation = this._getItemGroupLocation();
K
kener 已提交
60

K
kener 已提交
61 62
            this._buildBackground();
            this._buildItem();
K
kener 已提交
63

K
kener 已提交
64 65
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                this.zr.addShape(this.shapeList[i]);
K
kener 已提交
66
            }
K
kener 已提交
67
        },
K
kener 已提交
68 69 70 71

        /**
         * 构建所有图例元素
         */
72
        _buildItem: function () {
K
kener 已提交
73
            var data = this.legendOption.data;
K
kener 已提交
74 75 76 77 78
            var dataLength = data.length;
            var itemName;
            var itemType;
            var itemShape;
            var textShape;
K
kener 已提交
79
            var textStyle  = this.legendOption.textStyle;
80 81
            var dataTextStyle;
            var dataFont;
K
jshint  
kener 已提交
82
            var formattedName;
K
kener 已提交
83

K
kener 已提交
84 85 86 87 88 89 90
            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 已提交
91 92
            var color;

93
            if (this.legendOption.orient === 'vertical' && this.legendOption.x === 'right') {
K
kener 已提交
94 95
                lastX = this._itemGroupLocation.x
                        + this._itemGroupLocation.width
K
kener 已提交
96 97 98 99
                        - itemWidth;
            }

            for (var i = 0; i < dataLength; i++) {
100 101
                dataTextStyle = zrUtil.merge(
                    data[i].textStyle || {},
K
kener 已提交
102
                    textStyle
103
                );
K
kener 已提交
104
                dataFont = this.getFont(dataTextStyle);
105
                
K
kener 已提交
106
                itemName = this._getName(data[i]);
K
jshint  
kener 已提交
107
                formattedName = this._getFormatterName(itemName);
108 109
                if (itemName === '') { // 别帮我代码优化
                    if (this.legendOption.orient === 'horizontal') {
K
kener 已提交
110
                        lastX = this._itemGroupLocation.x;
K
kener 已提交
111 112 113
                        lastY += itemHeight + itemGap;
                    }
                    else {
114
                        this.legendOption.x === 'right'
K
kener 已提交
115 116
                            ? lastX -= this._itemGroupLocation.maxWidth + itemGap
                            : lastX += this._itemGroupLocation.maxWidth + itemGap;
K
kener 已提交
117
                        lastY = this._itemGroupLocation.y;
K
kener 已提交
118 119 120
                    }
                    continue;
                }
K
kener 已提交
121
                itemType = data[i].icon || this._getSomethingByName(itemName).type;
K
kener 已提交
122
                
K
kener 已提交
123
                color = this.getColor(itemName);
K
kener 已提交
124

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

                // 图形
K
kener 已提交
152
                itemShape = this._getItemShapeByType(
K
kener 已提交
153 154
                    lastX, lastY,
                    itemWidth, itemHeight,
K
kener 已提交
155
                    (this._selectedMap[itemName] ? color : '#ccc'),
156 157
                    itemType,
                    color
K
kener 已提交
158 159
                );
                itemShape._name = itemName;
K
kener 已提交
160
                itemShape = new IconShape(itemShape);
K
kener 已提交
161 162 163

                // 文字
                textShape = {
164 165 166 167 168 169
                    // shape: 'text',
                    zlevel: this._zlevelBase,
                    style: {
                        x: lastX + itemWidth + 5,
                        y: lastY + itemHeight / 2,
                        color: this._selectedMap[itemName]
170
                                ? (dataTextStyle.color === 'auto' ? color : dataTextStyle.color)
K
kener 已提交
171
                                : '#ccc',
F
fanlia 已提交
172
                        text: formattedName,
173
                        textFont: dataFont,
K
kener 已提交
174
                        textBaseline: 'middle'
K
kener 已提交
175
                    },
176 177
                    highlightStyle: {
                        color: color,
178 179
                        brushType: 'fill'
                    },
180 181
                    hoverable: !!this.legendOption.selectedMode,
                    clickable: !!this.legendOption.selectedMode
K
kener 已提交
182 183
                };

184 185
                if (this.legendOption.orient === 'vertical'
                    && this.legendOption.x === 'right'
K
kener 已提交
186 187 188 189 190 191
                ) {
                    textShape.style.x -= (itemWidth + 10);
                    textShape.style.textAlign = 'right';
                }

                textShape._name = itemName;
K
kener 已提交
192 193
                textShape = new TextShape(textShape);
                
K
kener 已提交
194
                if (this.legendOption.selectedMode) {
K
jshint  
kener 已提交
195
                    itemShape.onclick = textShape.onclick = this._legendSelected;
K
kener 已提交
196
                    itemShape.onmouseover =  textShape.onmouseover = this._dispatchHoverLink;
K
kener 已提交
197 198
                    itemShape.hoverConnect = textShape.id;
                    textShape.hoverConnect = itemShape.id;
199
                }
K
kener 已提交
200 201
                this.shapeList.push(itemShape);
                this.shapeList.push(textShape);
K
kener 已提交
202

203
                if (this.legendOption.orient === 'horizontal') {
K
kener 已提交
204
                    lastX += itemWidth + 5
F
fanlia 已提交
205
                             + zrArea.getTextWidth(formattedName, dataFont)
K
kener 已提交
206 207 208 209 210 211
                             + itemGap;
                }
                else {
                    lastY += itemHeight + itemGap;
                }
            }
K
kener 已提交
212
        
213 214
            if (this.legendOption.orient === 'horizontal'
                && this.legendOption.x === 'center'
K
kener 已提交
215
                && lastY != this._itemGroupLocation.y
K
kener 已提交
216 217
            ) {
                // 多行橫排居中优化
K
kener 已提交
218
                this._mLineOptimize();
K
kener 已提交
219
            }
K
kener 已提交
220
        },
K
kener 已提交
221
        
222
        _getName: function(data) {
K
kener 已提交
223 224
            return typeof data.name != 'undefined' ? data.name : data;
        },
F
fanlia 已提交
225 226 227 228

        _getFormatterName: function(itemName) {
            var formatter = this.legendOption.formatter;
            var formattedName;
229
            if (typeof formatter === 'function') {
F
fanlia 已提交
230 231
                formattedName = formatter.call(this.myChart, itemName);
            }
232
            else if (typeof formatter === 'string') {
F
fanlia 已提交
233 234 235 236 237 238 239 240 241 242 243 244
                formattedName = formatter.replace('{name}', itemName);
            }
            else {
                formattedName = itemName;
            }
            return formattedName;
        },

        _getFormatterNameFromData: function(data) {
            var itemName = this._getName(data);
            return this._getFormatterName(itemName);
        },
K
kener 已提交
245
        
K
kener 已提交
246
        // 多行橫排居中优化
247
        _mLineOptimize: function () {
K
kener 已提交
248
            var lineOffsetArray = []; // 每行宽度
K
kener 已提交
249 250
            var lastX = this._itemGroupLocation.x;
            for (var i = 2, l = this.shapeList.length; i < l; i++) {
251
                if (this.shapeList[i].style.x === lastX) {
K
kener 已提交
252 253
                    lineOffsetArray.push(
                        (
K
kener 已提交
254
                            this._itemGroupLocation.width 
K
kener 已提交
255
                            - (
K
kener 已提交
256
                                this.shapeList[i - 1].style.x
K
kener 已提交
257
                                + zrArea.getTextWidth(
K
kener 已提交
258 259
                                      this.shapeList[i - 1].style.text,
                                      this.shapeList[i - 1].style.textFont
K
kener 已提交
260 261 262 263 264
                                  )
                                - lastX
                            )
                        ) / 2
                    );
K
kener 已提交
265
                }
266
                else if (i === l - 1) {
K
kener 已提交
267 268
                    lineOffsetArray.push(
                        (
K
kener 已提交
269
                            this._itemGroupLocation.width 
K
kener 已提交
270
                            - (
K
kener 已提交
271
                                this.shapeList[i].style.x
K
kener 已提交
272
                                + zrArea.getTextWidth(
K
kener 已提交
273 274
                                      this.shapeList[i].style.text,
                                      this.shapeList[i].style.textFont
K
kener 已提交
275 276 277 278 279 280 281 282
                                  )
                                - lastX
                            )
                        ) / 2
                    );
                }
            }
            var curLineIndex = -1;
K
kener 已提交
283
            for (var i = 1, l = this.shapeList.length; i < l; i++) {
284
                if (this.shapeList[i].style.x === lastX) {
K
kener 已提交
285 286 287 288 289 290
                    curLineIndex++;
                }
                if (lineOffsetArray[curLineIndex] === 0) {
                    continue;
                }
                else {
K
kener 已提交
291
                    this.shapeList[i].style.x += lineOffsetArray[curLineIndex];
K
kener 已提交
292 293
                }
            }
K
kener 已提交
294
        },
K
kener 已提交
295

296
        _buildBackground: function () {
K
kener 已提交
297 298 299 300
            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 已提交
301

K
kener 已提交
302
            this.shapeList.push(new RectangleShape({
303
                zlevel: this._zlevelBase,
K
kener 已提交
304
                hoverable :false,
305 306 307 308 309 310 311 312 313
                style: {
                    x: this._itemGroupLocation.x - pLeft,
                    y: this._itemGroupLocation.y - pTop,
                    width: this._itemGroupLocation.width + pLeft + pRight,
                    height: this._itemGroupLocation.height + pTop + pBottom,
                    brushType: this.legendOption.borderWidth === 0 ? 'fill' : 'both',
                    color: this.legendOption.backgroundColor,
                    strokeColor: this.legendOption.borderColor,
                    lineWidth: this.legendOption.borderWidth
K
kener 已提交
314
                }
K
kener 已提交
315
            }));
K
kener 已提交
316
        },
K
kener 已提交
317 318 319 320

        /**
         * 根据选项计算图例实体的位置坐标
         */
321
        _getItemGroupLocation: function () {
K
kener 已提交
322
            var data = this.legendOption.data;
K
kener 已提交
323
            var dataLength = data.length;
K
kener 已提交
324 325 326 327 328
            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 已提交
329 330
            var totalWidth = 0;
            var totalHeight = 0;
K
kener 已提交
331 332 333
            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 已提交
334 335 336
            
            var temp = 0; // 宽高计算,用于多行判断
            var maxWidth = 0; // 垂直布局有用
337
            if (this.legendOption.orient === 'horizontal') {
K
kener 已提交
338
                // 水平布局,计算总宽度
K
kener 已提交
339
                totalHeight = itemHeight;
K
kener 已提交
340
                for (var i = 0; i < dataLength; i++) {
K
kener 已提交
341
                    if (this._getName(data[i]) === '') {
K
kener 已提交
342 343 344 345 346 347 348 349 350 351 352 353 354 355
                        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(
F
fanlia 已提交
356
                                  this._getFormatterNameFromData(data[i]),
357
                                  data[i].textStyle 
K
kener 已提交
358
                                  ? this.getFont(zrUtil.merge(
359
                                        data[i].textStyle || {},
K
kener 已提交
360
                                        textStyle
361 362
                                    ))
                                  : font
K
kener 已提交
363 364 365 366 367 368 369 370 371 372
                              )
                            + 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 已提交
373 374 375 376 377 378 379 380
                }
            }
            else {
                // 垂直布局,计算总高度
                for (var i = 0; i < dataLength; i++) {
                    maxWidth = Math.max(
                        maxWidth,
                        zrArea.getTextWidth(
F
fanlia 已提交
381
                            this._getFormatterNameFromData(data[i]),
382
                            data[i].textStyle 
K
kener 已提交
383
                            ? this.getFont(zrUtil.merge(
384
                                  data[i].textStyle || {},
K
kener 已提交
385
                                  textStyle
386 387
                              ))
                            : font
K
kener 已提交
388 389 390
                        )
                    );
                }
K
kener 已提交
391 392 393
                maxWidth += itemWidth;
                totalWidth = maxWidth;
                for (var i = 0; i < dataLength; i++) {
K
kener 已提交
394
                    if (this._getName(data[i]) === '') {
K
kener 已提交
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
                        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 已提交
417 418
            }

K
kener 已提交
419 420
            zrWidth = this.zr.getWidth();
            zrHeight = this.zr.getHeight();
K
kener 已提交
421
            var x;
K
kener 已提交
422
            switch (this.legendOption.x) {
K
kener 已提交
423 424 425 426
                case 'center' :
                    x = Math.floor((zrWidth - totalWidth) / 2);
                    break;
                case 'left' :
K
kener 已提交
427
                    x = this.legendOption.padding[3] + this.legendOption.borderWidth;
K
kener 已提交
428 429 430 431
                    break;
                case 'right' :
                    x = zrWidth
                        - totalWidth
K
kener 已提交
432 433 434
                        - this.legendOption.padding[1]
                        - this.legendOption.padding[3]
                        - this.legendOption.borderWidth * 2;
K
kener 已提交
435 436
                    break;
                default :
K
kener 已提交
437
                    x = this.parsePercent(this.legendOption.x, zrWidth);
K
kener 已提交
438 439
                    break;
            }
K
kener 已提交
440
            
K
kener 已提交
441
            var y;
K
kener 已提交
442
            switch (this.legendOption.y) {
K
kener 已提交
443
                case 'top' :
K
kener 已提交
444
                    y = this.legendOption.padding[0] + this.legendOption.borderWidth;
K
kener 已提交
445 446 447 448
                    break;
                case 'bottom' :
                    y = zrHeight
                        - totalHeight
K
kener 已提交
449 450 451
                        - this.legendOption.padding[0]
                        - this.legendOption.padding[2]
                        - this.legendOption.borderWidth * 2;
K
kener 已提交
452 453 454 455 456
                    break;
                case 'center' :
                    y = Math.floor((zrHeight - totalHeight) / 2);
                    break;
                default :
K
kener 已提交
457
                    y = this.parsePercent(this.legendOption.y, zrHeight);
K
kener 已提交
458 459 460 461
                    break;
            }

            return {
462 463 464 465 466
                x: x,
                y: y,
                width: totalWidth,
                height: totalHeight,
                maxWidth: maxWidth
K
kener 已提交
467
            };
K
kener 已提交
468
        },
K
kener 已提交
469 470

        /**
K
kener 已提交
471
         * 根据名称返回series数据或data
K
kener 已提交
472
         */
473
        _getSomethingByName: function (name) {
K
kener 已提交
474
            var series = this.option.series;
K
kener 已提交
475
            var data;
K
kener 已提交
476
            for (var i = 0, l = series.length; i < l; i++) {
477
                if (series[i].name === name) {
K
kener 已提交
478
                    // 系列名称优先
K
kener 已提交
479
                    return {
480 481 482 483 484
                        type: series[i].type,
                        series: series[i],
                        seriesIndex: i,
                        data: null,
                        dataIndex: -1
K
kener 已提交
485
                    };
K
kener 已提交
486 487
                }

K
kener 已提交
488
                if (
489 490 491 492 493
                    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
K
kener 已提交
494
                ) {
495 496
                    data = series[i].categories || series[i].data || series[i].nodes;

K
kener 已提交
497
                    for (var j = 0, k = data.length; j < k; j++) {
498
                        if (data[j].name === name) {
K
kener 已提交
499
                            return {
500 501 502 503 504
                                type: series[i].type,
                                series: series[i],
                                seriesIndex: i,
                                data: data[j],
                                dataIndex: j
K
kener 已提交
505
                            };
K
kener 已提交
506 507
                        }
                    }
K
kener 已提交
508
                }
K
kener 已提交
509
            }
K
kener 已提交
510
            return {
511 512 513 514 515
                type: 'bar',
                series: null,
                seriesIndex: -1,
                data: null,
                dataIndex: -1
K
kener 已提交
516
            };
K
kener 已提交
517
        },
K
kener 已提交
518
        
519
        _getItemShapeByType: function (x, y, width, height, color, itemType, defaultColor) {
K
kener 已提交
520
            var highlightColor = color === '#ccc' ? defaultColor : color;
521
            var itemShape = {
522 523 524 525 526 527 528 529 530 531
                zlevel: this._zlevelBase,
                style: {
                    iconType: 'legendicon' + itemType,
                    x: x,
                    y: y,
                    width: width,
                    height: height,
                    color: color,
                    strokeColor: color,
                    lineWidth: 2
532 533
                },
                highlightStyle: {
534 535 536
                    color: highlightColor,
                    strokeColor: highlightColor,
                    lineWidth: 1
537
                },
538 539
                hoverable: this.legendOption.selectedMode,
                clickable: this.legendOption.selectedMode
540
            };
K
kener 已提交
541 542 543 544 545 546 547 548
            
            var imageLocation;
            if (itemType.match('image')) {
                var imageLocation = itemType.replace(
                    new RegExp('^image:\\/\\/'), ''
                );
                itemType = 'image';
            }
549
            // 特殊设置
K
kener 已提交
550
            switch (itemType) {
551
                case 'line':
552
                    itemShape.style.brushType = 'stroke';
553 554
                    itemShape.highlightStyle.lineWidth = 3;
                    break;
555 556
                case 'radar':
                case 'scatter':
557
                    itemShape.highlightStyle.lineWidth = 3;
558
                    break;
559
                case 'k':
560
                    itemShape.style.brushType = 'both';
561 562
                    itemShape.highlightStyle.lineWidth = 3;
                    itemShape.highlightStyle.color =
K
kener 已提交
563 564
                    itemShape.style.color = this.query(this.ecTheme, 'k.itemStyle.normal.color') 
                                            || '#fff';
565
                    itemShape.style.strokeColor = color != '#ccc' 
K
kener 已提交
566 567
                        ? (this.query(this.ecTheme, 'k.itemStyle.normal.lineStyle.color') 
                           || '#ff3200')
568
                        : color;
K
kener 已提交
569
                    break;
570
                case 'image':
K
kener 已提交
571 572 573 574 575 576
                    itemShape.style.iconType = 'image';
                    itemShape.style.image = imageLocation;
                    if (color === '#ccc') {
                        itemShape.style.opacity = 0.5;
                    }
                    break;
K
kener 已提交
577
            }
578
            return itemShape;
K
kener 已提交
579
        },
K
kener 已提交
580

581
        __legendSelected: function (param) {
K
kener 已提交
582
            var itemName = param.target._name;
K
kener 已提交
583 584 585
            if (this.legendOption.selectedMode === 'single') {
                for (var k in this._selectedMap) {
                    this._selectedMap[k] = false;
K
kener 已提交
586 587
                }
            }
K
kener 已提交
588 589
            this._selectedMap[itemName] = !this._selectedMap[itemName];
            this.messageCenter.dispatch(
K
kener 已提交
590 591
                ecConfig.EVENT.LEGEND_SELECTED,
                param.event,
K
kener 已提交
592
                {
593 594
                    selected: this._selectedMap,
                    target: itemName
K
kener 已提交
595 596
                },
                this.myChart
K
kener 已提交
597
            );
K
kener 已提交
598
        },
K
kener 已提交
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
        
        /**
         * 产生hover link事件 
         */
        __dispatchHoverLink : function(param) {
            this.messageCenter.dispatch(
                ecConfig.EVENT.LEGEND_HOVERLINK,
                param.event,
                {
                    target: param.target._name
                },
                this.myChart
            );
            return;
        },
        
K
kener 已提交
615 616 617
        /**
         * 刷新
         */
618
        refresh: function (newOption) {
K
kener 已提交
619
            if (newOption) {
K
kener 已提交
620
                this.option = newOption || this.option;
K
kener 已提交
621
                this.option.legend = this.reformOption(this.option.legend);
K
kener 已提交
622
                // 补全padding属性
K
kener 已提交
623 624
                this.option.legend.padding = this.reformCssArray(
                    this.option.legend.padding
K
kener 已提交
625
                );
K
kener 已提交
626 627 628 629 630 631 632
                this.legendOption = this.option.legend;
                
                var data = this.legendOption.data || [];
                var itemName;
                var something;
                var color;
                var queryTarget;
K
kener 已提交
633 634 635 636 637 638 639
                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 已提交
640
                for (var i = 0, dataLength = data.length; i < dataLength; i++) {
K
kener 已提交
641
                    itemName = this._getName(data[i]);
K
kener 已提交
642 643 644 645 646 647 648 649 650
                    if (itemName === '') {
                        continue;
                    }
                    something = this._getSomethingByName(itemName);
                    if (!something.series) {
                        this._selectedMap[itemName] = false;
                    } 
                    else {
                        if (something.data
651 652 653
                            && (something.type === ecConfig.CHART_TYPE_PIE
                                || something.type === ecConfig.CHART_TYPE_FORCE
                                || something.type === ecConfig.CHART_TYPE_FUNNEL)
K
kener 已提交
654 655 656 657 658 659 660 661
                        ) {
                            queryTarget = [something.data, something.series];
                        }
                        else {
                            queryTarget = [something.series];
                        }
                        
                        color = this.getItemStyleColor(
K
kener 已提交
662
                            this.deepQuery(queryTarget, 'itemStyle.normal.color'),
K
kener 已提交
663 664 665 666 667 668 669
                            something.seriesIndex,
                            something.dataIndex,
                            something.data
                        );
                        if (color && something.type != ecConfig.CHART_TYPE_K) {
                            this.setColor(itemName, color);
                        }
K
kener 已提交
670 671 672
                        this._selectedMap[itemName] = 
                            typeof this._selectedMap[itemName] != 'undefined'
                            ? this._selectedMap[itemName] : true; 
K
kener 已提交
673 674
                    }
                }
K
kener 已提交
675
            }
K
kener 已提交
676 677 678
            this.clear();
            this._buildShape();
        },
K
kener 已提交
679
        
680
        getRelatedAmount: function(name) {
K
kener 已提交
681 682 683 684
            var amount = 0;
            var series = this.option.series;
            var data;
            for (var i = 0, l = series.length; i < l; i++) {
685
                if (series[i].name === name) {
K
kener 已提交
686 687 688 689 690
                    // 系列名称优先
                    amount++;
                }

                if (
691 692 693 694 695
                    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
K
kener 已提交
696 697 698 699 700
                ) {
                    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++) {
701
                        if (data[j].name === name && data[j].value != '-') {
K
kener 已提交
702
                            amount++;
K
kener 已提交
703 704 705 706 707 708
                        }
                    }
                }
            }
            return amount;
        },
K
kener 已提交
709

710
        setColor: function (legendName, color) {
K
kener 已提交
711 712
            this._colorMap[legendName] = color;
        },
K
kener 已提交
713

714
        getColor: function (legendName) {
K
kener 已提交
715 716
            if (!this._colorMap[legendName]) {
                this._colorMap[legendName] = this.zr.getColor(this._colorIndex++);
K
kener 已提交
717
            }
K
kener 已提交
718 719
            return this._colorMap[legendName];
        },
K
kener 已提交
720
        
721
        hasColor: function (legendName) {
K
kener 已提交
722 723
            return this._colorMap[legendName] ? this._colorMap[legendName] : false;
        },
K
kener 已提交
724

725
        add: function (name, color){
K
kener 已提交
726 727
            var data = this.legendOption.data;
            for (var i = 0, dataLength = data.length; i < dataLength; i++) {
728
                if (this._getName(data[i]) === name) {
K
kener 已提交
729 730 731 732
                    // 已有就不重复加了
                    return;
                }
            }
K
kener 已提交
733 734 735 736
            this.legendOption.data.push(name);
            this.setColor(name,color);
            this._selectedMap[name] = true;
        },
K
kener 已提交
737

738
        del: function (name){
K
kener 已提交
739
            var data = this.legendOption.data;
K
kener 已提交
740
            for (var i = 0, dataLength = data.length; i < dataLength; i++) {
741
                if (this._getName(data[i]) === name) {
K
kener 已提交
742
                    return this.legendOption.data.splice(i, 1);
K
kener 已提交
743 744
                }
            }
K
kener 已提交
745
        },
746 747 748 749 750 751
        
        /**
         * 特殊图形元素回调设置
         * @param {Object} name
         * @param {Object} itemShape
         */
752 753
        getItemShape: function (name) {
            if (name == null) {
K
kener 已提交
754 755
                return;
            }
756
            var shape;
K
kener 已提交
757 758
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                shape = this.shapeList[i];
759
                if (shape._name === name && shape.type != 'text') {
760 761 762
                    return shape;
                }
            }
K
kener 已提交
763
        },
764 765 766 767 768 769
        
        /**
         * 特殊图形元素回调设置
         * @param {Object} name
         * @param {Object} itemShape
         */
770
        setItemShape: function (name, itemShape) {
771
            var shape;
K
kener 已提交
772 773
            for (var i = 0, l = this.shapeList.length; i < l; i++) {
                shape = this.shapeList[i];
774
                if (shape._name === name && shape.type != 'text') {
K
kener 已提交
775
                    if (!this._selectedMap[name]) {
776 777 778
                        itemShape.style.color = '#ccc';
                        itemShape.style.strokeColor = '#ccc';
                    }
K
kener 已提交
779
                    this.zr.modShape(shape.id, itemShape);
780 781
                }
            }
K
kener 已提交
782
        },
K
kener 已提交
783

784
        isSelected: function (itemName) {
K
kener 已提交
785 786
            if (typeof this._selectedMap[itemName] != 'undefined') {
                return this._selectedMap[itemName];
K
kener 已提交
787 788 789 790 791
            }
            else {
                // 没在legend里定义的都为true啊~
                return true;
            }
K
kener 已提交
792
        },
K
kener 已提交
793
        
794
        getSelectedMap: function () {
K
kener 已提交
795 796
            return this._selectedMap;
        },
K
kener 已提交
797
        
798
        setSelected: function(itemName, selectStatus) {
K
kener 已提交
799 800 801 802 803 804 805 806
            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 已提交
807
                null,
K
kener 已提交
808
                {
809 810
                    selected: this._selectedMap,
                    target: itemName
K
kener 已提交
811 812
                },
                this.myChart
K
kener 已提交
813 814 815
            );
        },
        
K
kener 已提交
816 817 818
        /**
         * 图例选择
         */
819
        onlegendSelected: function (param, status) {
K
kener 已提交
820
            var legendSelected = param.selected;
K
kener 已提交
821
            for (var itemName in legendSelected) {
K
kener 已提交
822
                if (this._selectedMap[itemName] != legendSelected[itemName]) {
K
kener 已提交
823 824 825
                    // 有一项不一致都需要重绘
                    status.needRefresh = true;
                }
K
kener 已提交
826
                this._selectedMap[itemName] = legendSelected[itemName];
K
kener 已提交
827 828 829
            }
            return;
        }
K
jshint  
kener 已提交
830
    };
831 832
    
    var legendIcon = {
833
        line: function (ctx, style) {
834 835 836 837
            var dy = style.height / 2;
            ctx.moveTo(style.x,     style.y + dy);
            ctx.lineTo(style.x + style.width,style.y + dy);
        },
K
kener 已提交
838
        
839
        pie: function (ctx, style) {
840 841 842 843
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
K
kener 已提交
844
            SectorShape.prototype.buildPath(ctx, {
845 846 847 848 849 850
                x: x + width / 2,
                y: y + height + 2,
                r: height + 2,
                r0: 6,
                startAngle: 45,
                endAngle: 135
851
            });
K
kener 已提交
852
        },
K
kener 已提交
853 854
        
        eventRiver: function (ctx, style) {
K
kener 已提交
855 856 857 858 859
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
            ctx.moveTo(x, y + height);
K
kener 已提交
860 861 862
            ctx.bezierCurveTo(
                x + width, y + height, x, y + 4, x + width, y + 4
            );
K
kener 已提交
863
            ctx.lineTo(x + width, y);
K
kener 已提交
864 865 866
            ctx.bezierCurveTo(
                x, y, x + width, y + height - 4, x, y + height - 4
            );
K
kener 已提交
867 868
            ctx.lineTo(x, y + height);
        },
K
kener 已提交
869
        
870
        k: function (ctx, style) {
871 872 873 874
            var x = style.x;
            var y = style.y;
            var width = style.width;
            var height = style.height;
K
kener 已提交
875
            CandleShape.prototype.buildPath(ctx, {
876 877 878
                x: x + width / 2,
                y: [y + 1, y + 1, y + height - 6, y + height],
                width: width - 6
879 880
            });
        },
K
kener 已提交
881
        
882
        bar: function (ctx, style) {
K
kener 已提交
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
            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 已提交
904
        },
K
kener 已提交
905
        
906
        force: function (ctx, style) {
K
kener 已提交
907
            IconShape.prototype.iconLibrary.circle(ctx, style);
K
kener 已提交
908
        },
K
kener 已提交
909
        
K
kener 已提交
910
        radar: function (ctx, style) {
K
kener 已提交
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
            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);
928
        }
K
kener 已提交
929
    };
K
kener 已提交
930 931
    legendIcon.chord = legendIcon.pie;
    legendIcon.map = legendIcon.bar;
932
    
K
kener 已提交
933 934 935 936
    for (var k in legendIcon) {
        IconShape.prototype.iconLibrary['legendicon' + k] = legendIcon[k];
    }
    
K
kener 已提交
937 938
    zrUtil.inherits(Legend, Base);
    
939 940
    require('../component').define('legend', Legend);
    
K
kener 已提交
941 942 943 944
    return Legend;
});