legend.js 35.8 KB
Newer Older
K
kener 已提交
1 2 3 4
/**
 * echarts组件:图例
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
K
kener 已提交
5
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
K
kener 已提交
6 7 8
 *
 */
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
        this._colorIndex = 0;
        this._colorMap = {};
        this._selectedMap = {};
48
        this._hasDataMap = {};
K
kener 已提交
49 50
        
        this.refresh(option);
K
kener 已提交
51 52 53
    }
    
    Legend.prototype = {
54 55
        type: ecConfig.COMPONENT_TYPE_LEGEND,
        _buildShape: function () {
K
kener 已提交
56 57 58
            if (!this.legendOption.show) {
                return;
            }
K
kener 已提交
59
            // 图例元素组的位置参数,通过计算所得x, y, width, height
K
kener 已提交
60
            this._itemGroupLocation = this._getItemGroupLocation();
K
kener 已提交
61

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

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

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

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

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

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

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

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

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

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

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

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

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

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

298
        _buildBackground: function () {
K
kener 已提交
299
            var padding = this.reformCssArray(this.legendOption.padding);
K
kener 已提交
300

K
kener 已提交
301
            this.shapeList.push(new RectangleShape({
302 303
                zlevel: this.getZlevelBase(),
                z: this.getZBase(),
K
kener 已提交
304
                hoverable :false,
305
                style: {
K
kener 已提交
306 307 308 309
                    x: this._itemGroupLocation.x - padding[3],
                    y: this._itemGroupLocation.y - padding[0],
                    width: this._itemGroupLocation.width + padding[3] + padding[1],
                    height: this._itemGroupLocation.height + padding[0] + padding[2],
310 311 312 313
                    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
            var padding = this.reformCssArray(this.legendOption.padding);
K
kener 已提交
332 333
            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 = padding[3] + this.legendOption.borderWidth;
K
kener 已提交
428 429 430 431
                    break;
                case 'right' :
                    x = zrWidth
                        - totalWidth
K
kener 已提交
432 433
                        - padding[1]
                        - padding[3]
K
kener 已提交
434
                        - 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 = padding[0] + this.legendOption.borderWidth;
K
kener 已提交
445 446 447 448
                    break;
                case 'bottom' :
                    y = zrHeight
                        - totalHeight
K
kener 已提交
449 450
                        - padding[0]
                        - padding[2]
K
kener 已提交
451
                        - 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
                zlevel: this.getZlevelBase(),
                z: this.getZBase(),
524 525 526 527 528 529 530 531 532
                style: {
                    iconType: 'legendicon' + itemType,
                    x: x,
                    y: y,
                    width: width,
                    height: height,
                    color: color,
                    strokeColor: color,
                    lineWidth: 2
533 534
                },
                highlightStyle: {
535 536 537
                    color: highlightColor,
                    strokeColor: highlightColor,
                    lineWidth: 1
538
                },
539 540
                hoverable: this.legendOption.selectedMode,
                clickable: this.legendOption.selectedMode
541
            };
K
kener 已提交
542 543 544 545 546 547 548 549
            
            var imageLocation;
            if (itemType.match('image')) {
                var imageLocation = itemType.replace(
                    new RegExp('^image:\\/\\/'), ''
                );
                itemType = 'image';
            }
550
            // 特殊设置
K
kener 已提交
551
            switch (itemType) {
552
                case 'line':
553
                    itemShape.style.brushType = 'stroke';
554 555
                    itemShape.highlightStyle.lineWidth = 3;
                    break;
556 557
                case 'radar':
                case 'scatter':
558
                    itemShape.highlightStyle.lineWidth = 3;
559
                    break;
560
                case 'k':
561
                    itemShape.style.brushType = 'both';
562 563
                    itemShape.highlightStyle.lineWidth = 3;
                    itemShape.highlightStyle.color =
K
kener 已提交
564 565
                    itemShape.style.color = this.query(this.ecTheme, 'k.itemStyle.normal.color') 
                                            || '#fff';
566
                    itemShape.style.strokeColor = color != '#ccc' 
K
kener 已提交
567 568
                        ? (this.query(this.ecTheme, 'k.itemStyle.normal.lineStyle.color') 
                           || '#ff3200')
569
                        : color;
K
kener 已提交
570
                    break;
571
                case 'image':
K
kener 已提交
572 573 574 575 576 577
                    itemShape.style.iconType = 'image';
                    itemShape.style.image = imageLocation;
                    if (color === '#ccc') {
                        itemShape.style.opacity = 0.5;
                    }
                    break;
K
kener 已提交
578
            }
579
            return itemShape;
K
kener 已提交
580
        },
K
kener 已提交
581

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

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

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

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

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

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

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