tooltip.js 66.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 LineShape = require('zrender/shape/Line');
    var RectangleShape = require('zrender/shape/Rectangle');
K
kener 已提交
14
    var rectangleInstance = new RectangleShape({});
K
kener 已提交
15
    
K
kener 已提交
16 17 18 19 20 21 22 23 24
    var ecConfig = require('../config');
    var ecData = require('../util/ecData');
    var zrConfig = require('zrender/config');
    var zrEvent = require('zrender/tool/event');
    var zrArea = require('zrender/tool/area');
    var zrColor = require('zrender/tool/color');
    var zrUtil = require('zrender/tool/util');
    var zrShapeBase = require('zrender/shape/Base');

K
kener 已提交
25 26 27 28 29 30
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 提示框参数
     * @param {HtmlElement} dom 目标对象
K
kener 已提交
31
     * @param {ECharts} myChart 当前图表实例
K
kener 已提交
32
     */
K
kener 已提交
33 34
    function Tooltip(ecTheme, messageCenter, zr, option, myChart) {
        Base.call(this, ecTheme, messageCenter, zr, option, myChart);
K
kener 已提交
35
        
K
kener 已提交
36
        this.dom = myChart.dom;
K
kener 已提交
37 38 39
        
        var self = this;
        self._onmousemove = function (param) {
K
kener 已提交
40
            return self.__onmousemove(param);
K
kener 已提交
41 42
        };
        self._onglobalout = function (param) {
K
kener 已提交
43
            return self.__onglobalout(param);
K
kener 已提交
44 45 46 47
        };
        
        this.zr.on(zrConfig.EVENT.MOUSEMOVE, self._onmousemove);
        this.zr.on(zrConfig.EVENT.GLOBALOUT, self._onglobalout);
K
kener 已提交
48

K
kener 已提交
49
        self._hide = function (param) {
K
kener 已提交
50
            return self.__hide(param);
K
kener 已提交
51 52
        };
        self._tryShow = function(param) {
K
kener 已提交
53 54
            return self.__tryShow(param);
        };
K
kener 已提交
55
        self._refixed = function(param) {
K
kener 已提交
56 57
            return self.__refixed(param);
        };
K
kener 已提交
58
        
K
kener 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
        this._tDom = this._tDom || document.createElement('div');
        this._tDom.style.position = 'absolute';  // 不是多余的,别删!
        this.hasAppend = false;
        
        this._axisLineShape && this.zr.delShape(this._axisLineShape);
        this._axisLineShape = new LineShape({
            zlevel: this._zlevelBase,
            invisible : true,
            hoverable: false
        });
        this.shapeList.push(this._axisLineShape);
        this.zr.addShape(this._axisLineShape);
        
        this._axisShadowShape && this.zr.delShape(this._axisShadowShape);
        this._axisShadowShape = new LineShape({
            zlevel: 1,                      // grid上,chart下
            invisible : true,
            hoverable: false
        });
        this.shapeList.push(this._axisShadowShape);
        this.zr.addShape(this._axisShadowShape);
        
K
kener 已提交
81
        this.showing = false;
K
kener 已提交
82
        this.refresh(option);
K
kener 已提交
83 84 85 86 87 88 89 90 91
    }
    
    Tooltip.prototype = {
        type : ecConfig.COMPONENT_TYPE_TOOLTIP,
        // 通用样式
        _gCssText : 'position:absolute;'
                        + 'display:block;'
                        + 'border-style:solid;'
                        + 'white-space:nowrap;',
K
kener 已提交
92 93 94
        /**
         * 根据配置设置dom样式
         */
K
kener 已提交
95
        _style : function (opt) {
K
kener 已提交
96 97 98
            if (!opt) {
                return '';
            }
K
kener 已提交
99
            var cssText = [];
K
kener 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
            if (opt.transitionDuration) {
                var transitionText = 'left ' + opt.transitionDuration + 's,'
                                    + 'top ' + opt.transitionDuration + 's';
                cssText.push(
                    'transition:' + transitionText
                );
                cssText.push(
                    '-moz-transition:' + transitionText
                );
                cssText.push(
                    '-webkit-transition:' + transitionText
                );
                cssText.push(
                    '-o-transition:' + transitionText
                );
            }
K
kener 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

            if (opt.backgroundColor) {
                // for sb ie~
                cssText.push(
                    'background-Color:' + zrColor.toHex(
                        opt.backgroundColor
                    )
                );
                cssText.push('filter:alpha(opacity=70)');
                cssText.push('background-Color:' + opt.backgroundColor);
            }

            if (typeof opt.borderWidth != 'undefined') {
                cssText.push('border-width:' + opt.borderWidth + 'px');
            }

            if (typeof opt.borderColor != 'undefined') {
K
kener 已提交
133
                cssText.push('border-color:' + opt.borderColor);
K
kener 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
            }

            if (typeof opt.borderRadius != 'undefined') {
                cssText.push(
                    'border-radius:' + opt.borderRadius + 'px'
                );
                cssText.push(
                    '-moz-border-radius:' + opt.borderRadius + 'px'
                );
                cssText.push(
                    '-webkit-border-radius:' + opt.borderRadius + 'px'
                );
                cssText.push(
                    '-o-border-radius:' + opt.borderRadius + 'px'
                );
            }

            var textStyle = opt.textStyle;
            if (textStyle) {
                textStyle.color && cssText.push('color:' + textStyle.color);
                textStyle.decoration && cssText.push(
                    'text-decoration:' + textStyle.decoration
                );
                textStyle.align && cssText.push(
                    'text-align:' + textStyle.align
                );
                textStyle.fontFamily && cssText.push(
                    'font-family:' + textStyle.fontFamily
                );
                textStyle.fontSize && cssText.push(
                    'font-size:' + textStyle.fontSize + 'px'
                );
                textStyle.fontSize && cssText.push(
                    'line-height:' + Math.round(textStyle.fontSize*3/2) + 'px'
                );
                textStyle.fontStyle && cssText.push(
                    'font-style:' + textStyle.fontStyle
                );
                textStyle.fontWeight && cssText.push(
                    'font-weight:' + textStyle.fontWeight
                );
            }


            var padding = opt.padding;
            if (typeof padding != 'undefined') {
K
kener 已提交
180
                padding = this.reformCssArray(padding);
K
kener 已提交
181 182 183 184 185 186 187 188 189 190 191
                cssText.push(
                    'padding:' + padding[0] + 'px '
                               + padding[1] + 'px '
                               + padding[2] + 'px '
                               + padding[3] + 'px'
                );
            }

            cssText = cssText.join(';') + ';';

            return cssText;
K
kener 已提交
192 193 194 195 196
        },
        
        __hide : function () {
            if (this._tDom) {
                this._tDom.style.display = 'none';
K
kener 已提交
197
            }
198
            var needRefresh = false;
K
kener 已提交
199 200
            if (!this._axisLineShape.invisible) {
                this._axisLineShape.invisible = true;
K
kener 已提交
201
                this.zr.modShape(this._axisLineShape.id);
202 203
                needRefresh = true;
            }
K
kener 已提交
204 205
            if (!this._axisShadowShape.invisible) {
                this._axisShadowShape.invisible = true;
K
kener 已提交
206
                this.zr.modShape(this._axisShadowShape.id);
207
                needRefresh = true;
K
kener 已提交
208
            }
K
kener 已提交
209 210 211
            if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
                this.zr.delShape(this._lastTipShape.tipShape);
                this._lastTipShape = false;
K
kener 已提交
212
                this.shapeList.length = 2;
K
kener 已提交
213
            }
K
kener 已提交
214 215
            needRefresh && this.zr.refresh();
            this.showing = false;
K
kener 已提交
216 217 218 219 220 221
        },
        
        _show : function (x, y, specialCssText) {
            var domHeight = this._tDom.offsetHeight;
            var domWidth = this._tDom.offsetWidth;
            if (x + domWidth > this._zrWidth) {
K
kener 已提交
222
                // 太靠右
K
kener 已提交
223
                //x = this._zrWidth - domWidth;
K
kener 已提交
224
                x -= (domWidth + 40);
K
kener 已提交
225
            }
K
kener 已提交
226
            if (y + domHeight > this._zrHeight) {
K
kener 已提交
227
                // 太靠下
K
kener 已提交
228
                //y = this._zrHeight - domHeight;
K
kener 已提交
229
                y -= (domHeight - 20);
K
kener 已提交
230
            }
K
kener 已提交
231 232 233
            if (y < 20) {
                y = 0;
            }
K
kener 已提交
234 235
            this._tDom.style.cssText = this._gCssText
                                  + this._defaultCssText
K
kener 已提交
236 237
                                  + (specialCssText ? specialCssText : '')
                                  + 'left:' + x + 'px;top:' + y + 'px;';
K
kener 已提交
238 239
            
            if (domHeight < 10 || domWidth < 10) {
K
kener 已提交
240 241
                // this._zrWidth - x < 100 || this._zrHeight - y < 100
                setTimeout(this._refixed, 20);
K
kener 已提交
242
            }
K
kener 已提交
243
            this.showing = true;
K
kener 已提交
244
        },
K
kener 已提交
245
        
K
kener 已提交
246 247
        __refixed : function () {
            if (this._tDom) {
K
kener 已提交
248
                var cssText = '';
K
kener 已提交
249 250 251 252
                var domHeight = this._tDom.offsetHeight;
                var domWidth = this._tDom.offsetWidth;
                if (this._tDom.offsetLeft + domWidth > this._zrWidth) {
                    cssText += 'left:' + (this._zrWidth - domWidth - 20) + 'px;';
K
kener 已提交
253
                }
K
kener 已提交
254 255
                if (this._tDom.offsetTop + domHeight > this._zrHeight) {
                    cssText += 'top:' + (this._zrHeight - domHeight - 10) + 'px;';
K
kener 已提交
256 257
                }
                if (cssText !== '') {
K
kener 已提交
258
                    this._tDom.style.cssText += cssText;
K
kener 已提交
259 260
                }
            }
K
kener 已提交
261
        },
K
kener 已提交
262
        
K
kener 已提交
263
        __tryShow : function () {
K
kener 已提交
264 265
            var needShow;
            var trigger;
K
kener 已提交
266
            if (!this._curTarget) {
K
kener 已提交
267
                // 坐标轴事件
K
kener 已提交
268
                this._findPolarTrigger() || this._findAxisTrigger();
K
kener 已提交
269 270 271
            }
            else {
                // 数据项事件
K
kener 已提交
272
                if (this._curTarget._type == 'island' && this.option.tooltip.show) {
K
kener 已提交
273
                    this._showItemTrigger();
K
kener 已提交
274 275
                    return;
                }
K
kener 已提交
276 277 278
                var serie = ecData.get(this._curTarget, 'series');
                var data = ecData.get(this._curTarget, 'data');
                needShow = this.deepQuery(
K
kener 已提交
279
                    [data, serie, this.option],
K
kener 已提交
280 281 282 283 284 285 286
                    'tooltip.show'
                );
                if (typeof serie == 'undefined'
                    || typeof data == 'undefined'
                    || needShow === false
                ) {
                    // 不响应tooltip的数据对象延时隐藏
K
kener 已提交
287 288 289
                    clearTimeout(this._hidingTicket);
                    clearTimeout(this._showingTicket);
                    this._hidingTicket = setTimeout(this._hide, this._hideDelay);
K
kener 已提交
290 291
                }
                else {
K
kener 已提交
292
                    trigger = this.deepQuery(
K
kener 已提交
293
                        [data, serie, this.option],
K
kener 已提交
294 295 296
                        'tooltip.trigger'
                    );
                    trigger == 'axis'
K
kener 已提交
297
                               ? this._showAxisTrigger(
K
kener 已提交
298
                                     serie.xAxisIndex, serie.yAxisIndex,
K
kener 已提交
299
                                     ecData.get(this._curTarget, 'dataIndex')
K
kener 已提交
300
                                 )
K
kener 已提交
301
                               : this._showItemTrigger();
K
kener 已提交
302 303
                }
            }
K
kener 已提交
304
        },
K
kener 已提交
305

K
kener 已提交
306 307 308
        /**
         * 直角系 
         */
K
kener 已提交
309
        _findAxisTrigger : function () {
K
kener 已提交
310
            if (!this.component.xAxis || !this.component.yAxis) {
K
kener 已提交
311
                this._hidingTicket = setTimeout(this._hide, this._hideDelay);
K
kener 已提交
312 313
                return;
            }
K
kener 已提交
314
            var series = this.option.series;
K
kener 已提交
315 316
            var xAxisIndex;
            var yAxisIndex;
K
kener 已提交
317 318
            for (var i = 0, l = series.length; i < l; i++) {
                // 找到第一个axis触发tooltip的系列
K
kener 已提交
319 320
                if (this.deepQuery(
                        [series[i], this.option], 'tooltip.trigger'
K
kener 已提交
321 322 323 324
                    ) == 'axis'
                ) {
                    xAxisIndex = series[i].xAxisIndex || 0;
                    yAxisIndex = series[i].yAxisIndex || 0;
K
kener 已提交
325 326
                    if (this.component.xAxis.getAxis(xAxisIndex)
                        && this.component.xAxis.getAxis(xAxisIndex).type
K
kener 已提交
327 328 329
                           == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                    ) {
                        // 横轴为类目轴
K
kener 已提交
330
                        this._showAxisTrigger(xAxisIndex, yAxisIndex,
K
kener 已提交
331 332 333
                            this._getNearestDataIndex(
                                'x', this.component.xAxis.getAxis(xAxisIndex)
                            )
K
kener 已提交
334 335
                        );
                        return;
K
kener 已提交
336
                    } 
K
kener 已提交
337 338
                    else if (this.component.yAxis.getAxis(yAxisIndex)
                             && this.component.yAxis.getAxis(yAxisIndex).type
K
kener 已提交
339
                                == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
K
kener 已提交
340 341
                    ) {
                        // 纵轴为类目轴
K
kener 已提交
342
                        this._showAxisTrigger(xAxisIndex, yAxisIndex,
K
kener 已提交
343 344 345
                            this._getNearestDataIndex(
                                'y', this.component.yAxis.getAxis(yAxisIndex)
                            )
K
kener 已提交
346 347 348 349 350
                        );
                        return;
                    }
                }
            }
K
kener 已提交
351
        },
K
kener 已提交
352 353 354 355
        
        /**
         * 极坐标 
         */
K
kener 已提交
356
        _findPolarTrigger : function () {
K
kener 已提交
357
            if (!this.component.polar) {
K
kener 已提交
358 359
                return false;
            }
K
kener 已提交
360 361
            var x = zrEvent.getX(this._event);
            var y = zrEvent.getY(this._event);
K
kener 已提交
362
            var polarIndex = this.component.polar.getNearestIndex([x, y]);
K
kener 已提交
363 364 365 366 367 368 369 370 371 372
            var valueIndex;
            if (polarIndex) {
                valueIndex = polarIndex.valueIndex;
                polarIndex = polarIndex.polarIndex;
            }
            else {
                polarIndex = -1;
            }
            
            if (polarIndex != -1) {
K
kener 已提交
373
                return this._showPolarTrigger(polarIndex, valueIndex);
K
kener 已提交
374 375 376
            }
            
            return false;
K
kener 已提交
377
        },
K
kener 已提交
378
        
K
kener 已提交
379 380 381
        /**
         * 根据坐标轴事件带的属性获取最近的axisDataIndex
         */
K
kener 已提交
382
        _getNearestDataIndex : function (direction, categoryAxis) {
K
kener 已提交
383
            var dataIndex = -1;
K
kener 已提交
384 385
            var x = zrEvent.getX(this._event);
            var y = zrEvent.getY(this._event);
K
kener 已提交
386 387 388 389
            if (direction == 'x') {
                // 横轴为类目轴
                var left;
                var right;
K
kener 已提交
390
                var xEnd = this.component.grid.getXend();
K
kener 已提交
391 392 393 394 395 396 397 398 399 400 401 402
                var curCoord = categoryAxis.getCoordByIndex(dataIndex);
                while (curCoord < xEnd) {
                    if (curCoord <= x) {
                        left = curCoord;
                    }
                    if (curCoord >= x) {
                        break;
                    }
                    curCoord = categoryAxis.getCoordByIndex(++dataIndex);
                    right = curCoord;
                }
                if (x - left < right - x) {
K
kener 已提交
403
                    dataIndex -= dataIndex !== 0 ? 1 : 0;
K
kener 已提交
404 405 406 407 408 409
                }
                else {
                    // 离右边近,看是否为最后一个
                    if (typeof categoryAxis.getNameByIndex(dataIndex)
                        == 'undefined'
                    ) {
K
kener 已提交
410
                        dataIndex -= 1;
K
kener 已提交
411 412 413 414 415 416 417 418
                    }
                }
                return dataIndex;
            }
            else {
                // 纵轴为类目轴
                var top;
                var bottom;
K
kener 已提交
419
                var yStart = this.component.grid.getY();
K
kener 已提交
420 421 422 423 424 425 426 427 428 429 430 431 432
                var curCoord = categoryAxis.getCoordByIndex(dataIndex);
                while (curCoord > yStart) {
                    if (curCoord >= y) {
                        bottom = curCoord;
                    }
                    if (curCoord <= y) {
                        break;
                    }
                    curCoord = categoryAxis.getCoordByIndex(++dataIndex);
                    top = curCoord;
                }

                if (y - top > bottom - y) {
K
kener 已提交
433
                    dataIndex -= dataIndex !== 0 ? 1 : 0;
K
kener 已提交
434 435 436 437 438 439
                }
                else {
                    // 离上方边近,看是否为最后一个
                    if (typeof categoryAxis.getNameByIndex(dataIndex)
                        == 'undefined'
                    ) {
K
kener 已提交
440
                        dataIndex -= 1;
K
kener 已提交
441 442 443 444 445
                    }
                }
                return dataIndex;
            }
            return -1;
K
kener 已提交
446
        },
K
kener 已提交
447

K
kener 已提交
448 449 450
        /**
         * 直角系 
         */
K
kener 已提交
451 452
        _showAxisTrigger : function (xAxisIndex, yAxisIndex, dataIndex) {
            !this._event.connectTrigger && this.messageCenter.dispatch(
K
kener 已提交
453
                ecConfig.EVENT.TOOLTIP_IN_GRID,
K
kener 已提交
454
                this._event
K
kener 已提交
455
            );
K
kener 已提交
456 457
            if (typeof this.component.xAxis == 'undefined'
                || typeof this.component.yAxis == 'undefined'
K
kener 已提交
458 459 460 461 462
                || typeof xAxisIndex == 'undefined'
                || typeof yAxisIndex == 'undefined'
                || dataIndex < 0
            ) {
                // 不响应tooltip的数据对象延时隐藏
K
kener 已提交
463 464 465
                clearTimeout(this._hidingTicket);
                clearTimeout(this._showingTicket);
                this._hidingTicket = setTimeout(this._hide, this._hideDelay);
K
kener 已提交
466 467
                return;
            }
K
kener 已提交
468
            var series = this.option.series;
K
kener 已提交
469
            var seriesArray = [];
K
kener 已提交
470
            var seriesIndex = [];
K
kener 已提交
471 472 473 474 475
            var categoryAxis;
            var x;
            var y;

            var formatter;
K
kener 已提交
476
            var showContent;
K
kener 已提交
477
            var specialCssText = '';
K
kener 已提交
478 479
            if (this.option.tooltip.trigger == 'axis') {
                if (this.option.tooltip.show === false) {
K
kener 已提交
480 481
                    return;
                }
K
kener 已提交
482
                formatter = this.option.tooltip.formatter;
K
kener 已提交
483 484 485
            }

            if (xAxisIndex != -1
K
kener 已提交
486
                && this.component.xAxis.getAxis(xAxisIndex).type
K
kener 已提交
487 488 489
                   == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
            ) {
                // 横轴为类目轴,找到所有用这条横轴并且axis触发的系列数据
K
kener 已提交
490
                categoryAxis = this.component.xAxis.getAxis(xAxisIndex);
K
kener 已提交
491
                for (var i = 0, l = series.length; i < l; i++) {
K
kener 已提交
492
                    if (!this._isSelected(series[i].name)) {
K
kener 已提交
493 494
                        continue;
                    }
K
kener 已提交
495
                    if (series[i].xAxisIndex == xAxisIndex
K
kener 已提交
496 497
                        && this.deepQuery(
                               [series[i], this.option], 'tooltip.trigger'
K
kener 已提交
498 499
                           ) == 'axis'
                    ) {
K
kener 已提交
500
                        showContent = this.query(
501
                            series[i],
K
kener 已提交
502 503
                            'tooltip.showContent'
                        ) || showContent;
K
kener 已提交
504
                        formatter = this.query(
505
                            series[i],
K
kener 已提交
506 507
                            'tooltip.formatter'
                        ) || formatter;
K
kener 已提交
508
                        specialCssText += this._style(this.query(
509
                                              series[i], 'tooltip'
K
kener 已提交
510 511
                                          ));
                        seriesArray.push(series[i]);
K
kener 已提交
512
                        seriesIndex.push(i);
K
kener 已提交
513 514
                    }
                }
K
kener 已提交
515
                // 寻找高亮元素
K
kener 已提交
516
                this.messageCenter.dispatch(
K
kener 已提交
517
                    ecConfig.EVENT.TOOLTIP_HOVER,
K
kener 已提交
518
                    this._event,
K
kener 已提交
519 520
                    {
                        seriesIndex : seriesIndex,
K
kener 已提交
521 522
                        dataIndex : dataIndex
                        /*
K
kener 已提交
523 524
                        dataIndex : this.component.dataZoom
                                    ? this.component.dataZoom.getRealDataIndex(
K
kener 已提交
525
                                        seriesIndex[0],
526 527 528
                                        dataIndex
                                      )
                                    : dataIndex
K
kener 已提交
529
                                    */
K
kener 已提交
530 531
                    }
                );
K
kener 已提交
532 533
                y = zrEvent.getY(this._event) + 10;
                x = this.subPixelOptimize(
K
kener 已提交
534
                    categoryAxis.getCoordByIndex(dataIndex),
K
kener 已提交
535
                    this._axisLineWidth
K
kener 已提交
536
                );
K
kener 已提交
537
                this._styleAxisPointer(
538
                    seriesArray,
K
kener 已提交
539 540
                    x, this.component.grid.getY(), 
                    x, this.component.grid.getYend(),
541 542
                    categoryAxis.getGap()
                );
K
kener 已提交
543 544 545
                x += 10;
            }
            else if (yAxisIndex != -1
K
kener 已提交
546
                     && this.component.yAxis.getAxis(yAxisIndex).type
547
                        == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
K
kener 已提交
548 549
            ) {
                // 纵轴为类目轴,找到所有用这条纵轴并且axis触发的系列数据
K
kener 已提交
550
                categoryAxis = this.component.yAxis.getAxis(yAxisIndex);
K
kener 已提交
551
                for (var i = 0, l = series.length; i < l; i++) {
K
kener 已提交
552
                    if (!this._isSelected(series[i].name)) {
K
kener 已提交
553 554
                        continue;
                    }
K
kener 已提交
555
                    if (series[i].yAxisIndex == yAxisIndex
K
kener 已提交
556 557
                        && this.deepQuery(
                               [series[i], this.option], 'tooltip.trigger'
K
kener 已提交
558 559
                           ) == 'axis'
                    ) {
K
kener 已提交
560
                        showContent = this.query(
561
                            series[i],
K
kener 已提交
562 563
                            'tooltip.showContent'
                        ) || showContent;
K
kener 已提交
564
                        formatter = this.query(
565
                            series[i],
K
kener 已提交
566 567
                            'tooltip.formatter'
                        ) || formatter;
K
kener 已提交
568
                        specialCssText += this._style(this.query(
569
                                              series[i], 'tooltip'
K
kener 已提交
570 571
                                          ));
                        seriesArray.push(series[i]);
K
kener 已提交
572
                        seriesIndex.push(i);
K
kener 已提交
573 574
                    }
                }
K
kener 已提交
575
                // 寻找高亮元素
K
kener 已提交
576
                this.messageCenter.dispatch(
K
kener 已提交
577
                    ecConfig.EVENT.TOOLTIP_HOVER,
K
kener 已提交
578
                    this._event,
K
kener 已提交
579 580
                    {
                        seriesIndex : seriesIndex,
K
kener 已提交
581 582
                        dataIndex : dataIndex
                        /*
K
kener 已提交
583 584
                        dataIndex : this.component.dataZoom
                                    ? this.component.dataZoom.getRealDataIndex(
K
kener 已提交
585
                                        seriesIndex[0],
586 587 588
                                        dataIndex
                                      )
                                    : dataIndex
K
kener 已提交
589
                                    */
K
kener 已提交
590 591
                    }
                );
K
kener 已提交
592 593
                x = zrEvent.getX(this._event) + 10;
                y = this.subPixelOptimize(
K
kener 已提交
594
                    categoryAxis.getCoordByIndex(dataIndex),
K
kener 已提交
595
                    this._axisLineWidth
K
kener 已提交
596
                );
K
kener 已提交
597
                this._styleAxisPointer(
598
                    seriesArray,
K
kener 已提交
599 600
                    this.component.grid.getX(), y, 
                    this.component.grid.getXend(), y,
601 602
                    categoryAxis.getGap()
                );
K
kener 已提交
603 604 605 606 607 608 609 610
                y += 10;
            }

            if (seriesArray.length > 0) {
                var data;
                if (typeof formatter == 'function') {
                    var params = [];
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
K
kener 已提交
611 612 613 614 615 616 617
                        data = seriesArray[i].data[dataIndex];
                        data = typeof data != 'undefined'
                               ? (typeof data.value != 'undefined'
                                   ? data.value
                                   : data)
                               : '-';
                               
K
kener 已提交
618
                        params.push([
K
kener 已提交
619
                            seriesArray[i].name || '',
K
kener 已提交
620 621 622 623
                            categoryAxis.getNameByIndex(dataIndex),
                            data
                        ]);
                    }
K
kener 已提交
624 625 626
                    this._curTicket = 'axis:' + dataIndex;
                    this._tDom.innerHTML = formatter(
                        params, this._curTicket, this._setContent
K
kener 已提交
627 628 629
                    );
                }
                else if (typeof formatter == 'string') {
K
kener 已提交
630
                    this._curTicket = NaN;
K
kener 已提交
631 632 633 634 635 636
                    formatter = formatter.replace('{a}','{a0}')
                                         .replace('{b}','{b0}')
                                         .replace('{c}','{c0}');
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
                        formatter = formatter.replace(
                            '{a' + i + '}',
K
kener 已提交
637
                            this._encodeHTML(seriesArray[i].name || '')
K
kener 已提交
638 639 640
                        );
                        formatter = formatter.replace(
                            '{b' + i + '}',
K
kener 已提交
641
                            this._encodeHTML(categoryAxis.getNameByIndex(dataIndex))
K
kener 已提交
642
                        );
K
kener 已提交
643 644 645 646 647 648
                        data = seriesArray[i].data[dataIndex];
                        data = typeof data != 'undefined'
                               ? (typeof data.value != 'undefined'
                                   ? data.value
                                   : data)
                               : '-';
K
kener 已提交
649 650
                        formatter = formatter.replace(
                            '{c' + i + '}',
651
                            data instanceof Array 
K
kener 已提交
652
                            ? data : this.numAddCommas(data)
K
kener 已提交
653 654
                        );
                    }
K
kener 已提交
655
                    this._tDom.innerHTML = formatter;
K
kener 已提交
656 657
                }
                else {
K
kener 已提交
658 659
                    this._curTicket = NaN;
                    formatter = this._encodeHTML(
K
kener 已提交
660 661 662
                        categoryAxis.getNameByIndex(dataIndex)
                    );

K
kener 已提交
663
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
K
kener 已提交
664
                        formatter += '<br/>' 
K
kener 已提交
665
                                     + this._encodeHTML(seriesArray[i].name || '')
K
kener 已提交
666
                                     + ' : ';
K
kener 已提交
667
                        data = seriesArray[i].data[dataIndex];
K
kener 已提交
668
                        data = typeof data != 'undefined'
K
kener 已提交
669 670 671 672
                               ? (typeof data.value != 'undefined'
                                   ? data.value
                                   : data)
                               : '-';
673
                        formatter += data instanceof Array 
K
kener 已提交
674
                                     ? data : this.numAddCommas(data);
K
kener 已提交
675
                    }
K
kener 已提交
676
                    this._tDom.innerHTML = formatter;
K
kener 已提交
677 678
                }

K
kener 已提交
679
                if (showContent === false || !this.option.tooltip.showContent) {
K
kener 已提交
680 681 682 683
                    // 只用tooltip的行为,不显示主体
                    return;
                }
                
K
kener 已提交
684 685 686 687 688
                if (!this.hasAppend) {
                    this._tDom.style.left = this._zrWidth / 2 + 'px';
                    this._tDom.style.top = this._zrHeight / 2 + 'px';
                    this.dom.firstChild.appendChild(this._tDom);
                    this.hasAppend = true;
K
kener 已提交
689
                }
K
kener 已提交
690
                this._show(x, y, specialCssText);
K
kener 已提交
691
            }
K
kener 已提交
692
        },
693
        
K
kener 已提交
694 695 696
        /**
         * 极坐标 
         */
K
kener 已提交
697
        _showPolarTrigger : function (polarIndex, dataIndex) {
K
kener 已提交
698
            if (typeof this.component.polar == 'undefined'
K
kener 已提交
699 700 701 702 703 704
                || typeof polarIndex == 'undefined'
                || typeof dataIndex == 'undefined'
                || dataIndex < 0
            ) {
                return false;
            }
K
kener 已提交
705
            var series = this.option.series;
K
kener 已提交
706 707 708
            var seriesArray = [];

            var formatter;
K
kener 已提交
709
            var showContent;
K
kener 已提交
710
            var specialCssText = '';
K
kener 已提交
711 712
            if (this.option.tooltip.trigger == 'axis') {
                if (this.option.tooltip.show === false) {
K
kener 已提交
713 714
                    return false;
                }
K
kener 已提交
715
                formatter = this.option.tooltip.formatter;
K
kener 已提交
716
            }
K
kener 已提交
717
            var indicatorName = 
K
kener 已提交
718
                    this.option.polar[polarIndex].indicator[dataIndex].text;
K
kener 已提交
719 720 721

            // 找到所有用这个极坐标并且axis触发的系列数据
            for (var i = 0, l = series.length; i < l; i++) {
K
kener 已提交
722
                if (!this._isSelected(series[i].name)) {
K
kener 已提交
723 724
                    continue;
                }
K
kener 已提交
725
                if (series[i].polarIndex == polarIndex
K
kener 已提交
726 727
                    && this.deepQuery(
                           [series[i], this.option], 'tooltip.trigger'
K
kener 已提交
728 729
                       ) == 'axis'
                ) {
K
kener 已提交
730
                    showContent = this.query(
731
                        series[i],
K
kener 已提交
732 733
                        'tooltip.showContent'
                    ) || showContent;
K
kener 已提交
734
                    formatter = this.query(
735
                        series[i],
K
kener 已提交
736 737
                        'tooltip.formatter'
                    ) || formatter;
K
kener 已提交
738
                    specialCssText += this._style(this.query(
739
                                          series[i], 'tooltip'
K
kener 已提交
740 741 742 743 744 745 746 747 748 749 750 751 752
                                      ));
                    seriesArray.push(series[i]);
                }
            }
            if (seriesArray.length > 0) {
                var polarData;
                var data;
                var params = [];

                for (var i = 0, l = seriesArray.length; i < l; i++) {
                    polarData = seriesArray[i].data;
                    for (var j = 0, k = polarData.length; j < k; j++) {
                        data = polarData[j];
K
kener 已提交
753
                        if (!this._isSelected(data.name)) {
K
kener 已提交
754 755
                            continue;
                        }
K
kener 已提交
756 757 758 759 760
                        data = typeof data != 'undefined'
                               ? data
                               : {name:'', value: {dataIndex:'-'}};
                               
                        params.push([
K
kener 已提交
761
                            seriesArray[i].name || '',
K
kener 已提交
762 763 764 765 766 767
                            data.name,
                            data.value[dataIndex],
                            indicatorName
                        ]);
                    }
                }
K
kener 已提交
768 769 770
                if (params.length <= 0) {
                    return;
                }
K
kener 已提交
771
                if (typeof formatter == 'function') {
K
kener 已提交
772 773 774
                    this._curTicket = 'axis:' + dataIndex;
                    this._tDom.innerHTML = formatter(
                        params, this._curTicket, this._setContent
K
kener 已提交
775 776 777 778 779 780 781 782 783 784
                    );
                }
                else if (typeof formatter == 'string') {
                    formatter = formatter.replace('{a}','{a0}')
                                         .replace('{b}','{b0}')
                                         .replace('{c}','{c0}')
                                         .replace('{d}','{d0}');
                    for (var i = 0, l = params.length; i < l; i++) {
                        formatter = formatter.replace(
                            '{a' + i + '}',
K
kener 已提交
785
                            this._encodeHTML(params[i][0])
K
kener 已提交
786 787 788
                        );
                        formatter = formatter.replace(
                            '{b' + i + '}',
K
kener 已提交
789
                            this._encodeHTML(params[i][1])
K
kener 已提交
790 791 792
                        );
                        formatter = formatter.replace(
                            '{c' + i + '}',
K
kener 已提交
793
                            this.numAddCommas(params[i][2])
K
kener 已提交
794 795 796
                        );
                        formatter = formatter.replace(
                            '{d' + i + '}',
K
kener 已提交
797
                            this._encodeHTML(params[i][3])
K
kener 已提交
798 799
                        );
                    }
K
kener 已提交
800
                    this._tDom.innerHTML = formatter;
K
kener 已提交
801 802
                }
                else {
K
kener 已提交
803 804 805
                    formatter = this._encodeHTML(params[0][1]) + '<br/>' 
                                + this._encodeHTML(params[0][3]) + ' : ' 
                                + this.numAddCommas(params[0][2]);
K
kener 已提交
806
                    for (var i = 1, l = params.length; i < l; i++) {
K
kener 已提交
807
                        formatter += '<br/>' + this._encodeHTML(params[i][1]) 
K
kener 已提交
808
                                     + '<br/>';
K
kener 已提交
809 810
                        formatter += this._encodeHTML(params[i][3]) + ' : ' 
                                     + this.numAddCommas(params[i][2]);
K
kener 已提交
811
                    }
K
kener 已提交
812
                    this._tDom.innerHTML = formatter;
K
kener 已提交
813 814
                }

K
kener 已提交
815
                if (showContent === false || !this.option.tooltip.showContent) {
K
kener 已提交
816 817 818 819
                    // 只用tooltip的行为,不显示主体
                    return;
                }
                
K
kener 已提交
820 821 822 823 824
                if (!this.hasAppend) {
                    this._tDom.style.left = this._zrWidth / 2 + 'px';
                    this._tDom.style.top = this._zrHeight / 2 + 'px';
                    this.dom.firstChild.appendChild(this._tDom);
                    this.hasAppend = true;
K
kener 已提交
825
                }
K
kener 已提交
826 827 828
                this._show(
                    zrEvent.getX(this._event), 
                    zrEvent.getY(this._event), 
K
kener 已提交
829 830 831 832
                    specialCssText
                );
                return true;
            }
K
kener 已提交
833
        },
K
kener 已提交
834
        
K
kener 已提交
835 836 837 838 839 840 841
        _showItemTrigger : function () {
            var serie = ecData.get(this._curTarget, 'series');
            var data = ecData.get(this._curTarget, 'data');
            var name = ecData.get(this._curTarget, 'name');
            var value = ecData.get(this._curTarget, 'value');
            var special = ecData.get(this._curTarget, 'special');
            var special2 = ecData.get(this._curTarget, 'special2');
K
kener 已提交
842 843
            // 从低优先级往上找到trigger为item的formatter和样式
            var formatter;
K
kener 已提交
844
            var showContent;
K
kener 已提交
845
            var specialCssText = '';
K
kener 已提交
846 847
            var indicator;
            var html = '';
K
kener 已提交
848
            if (this._curTarget._type != 'island') {
K
kener 已提交
849
                // 全局
K
kener 已提交
850 851
                if (this.option.tooltip.trigger == 'item') {
                    formatter = this.option.tooltip.formatter;
K
kener 已提交
852 853
                }
                // 系列
K
kener 已提交
854 855
                if (this.query(serie, 'tooltip.trigger') == 'item') {
                    showContent = this.query(
856
                                      serie, 'tooltip.showContent'
K
kener 已提交
857
                                  ) || showContent;
K
kener 已提交
858
                    formatter = this.query(
859
                                    serie, 'tooltip.formatter'
K
kener 已提交
860
                                ) || formatter;
K
kener 已提交
861
                    specialCssText += this._style(this.query(
862
                                          serie, 'tooltip'
K
kener 已提交
863 864 865
                                      ));
                }
                // 数据项
K
kener 已提交
866
                showContent = this.query(
867
                                  data, 'tooltip.showContent'
K
kener 已提交
868
                              ) || showContent;
K
kener 已提交
869
                formatter = this.query(
870
                                data, 'tooltip.formatter'
K
kener 已提交
871
                            ) || formatter;
K
kener 已提交
872
                specialCssText += this._style(this.query(data, 'tooltip'));
K
格式  
kener 已提交
873 874
            }
            else {
K
kener 已提交
875 876
                showContent = this.deepQuery(
                    [data, serie, this.option],
K
kener 已提交
877 878
                    'tooltip.showContent'
                );
K
kener 已提交
879 880
                formatter = this.deepQuery(
                    [data, serie, this.option],
K
kener 已提交
881 882 883 884 885
                    'tooltip.islandFormatter'
                );
            }

            if (typeof formatter == 'function') {
K
kener 已提交
886
                this._curTicket = (serie.name || '')
K
kener 已提交
887
                             + ':'
K
kener 已提交
888 889
                             + ecData.get(this._curTarget, 'dataIndex');
                this._tDom.innerHTML = formatter(
K
kener 已提交
890
                    [
K
kener 已提交
891
                        serie.name || '',
K
kener 已提交
892 893
                        name,
                        value,
L
lang 已提交
894 895
                        special,
                        special2
K
kener 已提交
896
                    ],
K
kener 已提交
897 898
                    this._curTicket,
                    this._setContent
K
kener 已提交
899 900 901
                );
            }
            else if (typeof formatter == 'string') {
K
kener 已提交
902
                this._curTicket = NaN;
K
kener 已提交
903 904
                formatter = formatter.replace('{a}','{a0}')
                                     .replace('{b}','{b0}')
K
kener 已提交
905 906
                                     .replace('{c}','{c0}');
                formatter = formatter.replace(
K
kener 已提交
907
                                          '{a0}', this._encodeHTML(serie.name || '')
K
kener 已提交
908
                                      )
K
kener 已提交
909
                                     .replace('{b0}', this._encodeHTML(name))
910 911 912
                                     .replace(
                                         '{c0}', 
                                         value instanceof Array
K
kener 已提交
913
                                         ? value : this.numAddCommas(value)
914
                                     );
K
kener 已提交
915

K
kener 已提交
916 917 918
                formatter = formatter.replace('{d}','{d0}')
                                     .replace('{d0}', special || '');
                formatter = formatter.replace('{e}','{e0}')
K
kener 已提交
919
                    .replace('{e0}', ecData.get(this._curTarget, 'special2') || '');
K
kener 已提交
920

K
kener 已提交
921
                this._tDom.innerHTML = formatter;
K
kener 已提交
922 923
            }
            else {
K
kener 已提交
924
                this._curTicket = NaN;
K
kener 已提交
925
                if (serie.type == ecConfig.CHART_TYPE_SCATTER) {
K
kener 已提交
926 927
                    this._tDom.innerHTML = (typeof serie.name != 'undefined'
                                          ? (this._encodeHTML(serie.name) + '<br/>')
K
kener 已提交
928 929 930
                                          : ''
                                      ) 
                                      + (name === '' 
K
kener 已提交
931
                                            ? '' : (this._encodeHTML(name) + ' : ')
K
kener 已提交
932 933
                                      ) 
                                      + value 
K
kener 已提交
934
                                      + (typeof special == 'undefined'
K
kener 已提交
935
                                          ? ''
K
kener 已提交
936
                                          : (' (' + special + ')'));
K
kener 已提交
937
                }
K
kener 已提交
938
                else if (serie.type == ecConfig.CHART_TYPE_RADAR && special) {
K
kener 已提交
939
                    indicator = special;
K
kener 已提交
940
                    html += this._encodeHTML(
K
kener 已提交
941 942 943
                        name === '' ? (serie.name || '') : name
                    );
                    html += html === '' ? '' : '<br />';
K
kener 已提交
944
                    for (var i = 0 ; i < indicator.length; i ++) {
K
kener 已提交
945 946
                        html += this._encodeHTML(indicator[i].text) + ' : ' 
                                + this.numAddCommas(value[i]) + '<br />';
K
kener 已提交
947
                    }
K
kener 已提交
948
                    this._tDom.innerHTML = html;
K
kener 已提交
949
                }
K
kener 已提交
950 951 952
                else if (serie.type == ecConfig.CHART_TYPE_CHORD) {
                    if (typeof special2 == 'undefined') {
                        // 外环上
K
kener 已提交
953 954
                        this._tDom.innerHTML = this._encodeHTML(name) + ' (' 
                                          + this.numAddCommas(value) + ')';
K
kener 已提交
955 956
                    }
                    else {
K
kener 已提交
957 958
                        var name1 = this._encodeHTML(name);
                        var name2 = this._encodeHTML(special);
K
kener 已提交
959
                        // 内部弦上
K
kener 已提交
960 961
                        this._tDom.innerHTML = (typeof serie.name != 'undefined'
                                          ? (this._encodeHTML(serie.name) + '<br/>')
K
kener 已提交
962
                                          : '')
963
                              + name1 + ' -> ' + name2 
K
kener 已提交
964
                              + ' (' + this.numAddCommas(value) + ')'
L
lang 已提交
965
                              + '<br />'
966
                              + name2 + ' -> ' + name1
K
kener 已提交
967
                              + ' (' + this.numAddCommas(special2) + ')';
K
kener 已提交
968 969
                    }
                }
K
kener 已提交
970
                else {
K
kener 已提交
971 972
                    this._tDom.innerHTML = (typeof serie.name != 'undefined'
                                      ? (this._encodeHTML(serie.name) + '<br/>')
K
kener 已提交
973
                                      : '')
K
kener 已提交
974 975
                                      + this._encodeHTML(name) + ' : ' 
                                      + this.numAddCommas(value) +
K
kener 已提交
976
                                      (typeof special == 'undefined'
K
kener 已提交
977
                                      ? ''
K
kener 已提交
978
                                      : (' ('+ this.numAddCommas(special) +')')
979
                                      );
K
kener 已提交
980
                }
K
kener 已提交
981 982
            }

K
kener 已提交
983 984
            if (!this._axisLineShape.invisible) {
                this._axisLineShape.invisible = true;
K
kener 已提交
985
                this.zr.modShape(this._axisLineShape.id);
K
kener 已提交
986
                this.zr.refresh();
K
kener 已提交
987 988
            }
            
K
kener 已提交
989
            if (showContent === false || !this.option.tooltip.showContent) {
K
kener 已提交
990 991 992 993
                // 只用tooltip的行为,不显示主体
                return;
            }
            
K
kener 已提交
994 995 996 997 998
            if (!this.hasAppend) {
                this._tDom.style.left = this._zrWidth / 2 + 'px';
                this._tDom.style.top = this._zrHeight / 2 + 'px';
                this.dom.firstChild.appendChild(this._tDom);
                this.hasAppend = true;
K
kener 已提交
999 1000
            }

K
kener 已提交
1001 1002 1003
            this._show(
                zrEvent.getX(this._event) + 20,
                zrEvent.getY(this._event) - 20,
K
kener 已提交
1004 1005
                specialCssText
            );
K
kener 已提交
1006
        },
K
kener 已提交
1007

1008 1009 1010
        /**
         * 设置坐标轴指示器样式 
         */
K
kener 已提交
1011
        _styleAxisPointer : function (seriesArray, xStart, yStart, xEnd, yEnd, gap) {
1012 1013 1014
            if (seriesArray.length > 0) {
                var queryTarget;
                var curType;
K
kener 已提交
1015
                var axisPointer = this.option.tooltip.axisPointer;
1016 1017 1018 1019 1020 1021 1022 1023
                var pointType = axisPointer.type;
                var lineColor = axisPointer.lineStyle.color;
                var lineWidth = axisPointer.lineStyle.width;
                var lineType = axisPointer.lineStyle.type;
                var areaSize = axisPointer.areaStyle.size;
                var areaColor = axisPointer.areaStyle.color;
                
                for (var i = 0, l = seriesArray.length; i < l; i++) {
K
kener 已提交
1024 1025
                    if (this.deepQuery(
                           [seriesArray[i], this.option], 'tooltip.trigger'
1026 1027
                       ) == 'axis'
                    ) {
1028
                        queryTarget = seriesArray[i];
K
kener 已提交
1029
                        curType = this.query(
1030 1031 1032 1033 1034
                            queryTarget,
                            'tooltip.axisPointer.type'
                        );
                        pointType = curType || pointType; 
                        if (curType == 'line') {
K
kener 已提交
1035
                            lineColor = this.query(
1036 1037 1038
                                queryTarget,
                                'tooltip.axisPointer.lineStyle.color'
                            ) || lineColor;
K
kener 已提交
1039
                            lineWidth = this.query(
1040 1041 1042
                                queryTarget,
                                'tooltip.axisPointer.lineStyle.width'
                            ) || lineWidth;
K
kener 已提交
1043
                            lineType = this.query(
1044 1045 1046 1047 1048
                                queryTarget,
                                'tooltip.axisPointer.lineStyle.type'
                            ) || lineType;
                        }
                        else if (curType == 'shadow') {
K
kener 已提交
1049
                            areaSize = this.query(
1050 1051 1052
                                queryTarget,
                                'tooltip.axisPointer.areaStyle.size'
                            ) || areaSize;
K
kener 已提交
1053
                            areaColor = this.query(
1054 1055 1056 1057 1058 1059 1060 1061
                                queryTarget,
                                'tooltip.axisPointer.areaStyle.color'
                            ) || areaColor;
                        }
                    }
                }
                
                if (pointType == 'line') {
K
kener 已提交
1062
                    this._axisLineShape.style = {
1063 1064 1065 1066 1067 1068 1069 1070
                        xStart : xStart,
                        yStart : yStart,
                        xEnd : xEnd,
                        yEnd : yEnd,
                        strokeColor : lineColor,
                        lineWidth : lineWidth,
                        lineType : lineType
                    };
K
kener 已提交
1071
                    this._axisLineShape.invisible = false;
K
kener 已提交
1072
                    this.zr.modShape(this._axisLineShape.id);
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
                }
                else if (pointType == 'shadow') {
                    if (typeof areaSize == 'undefined' 
                        || areaSize == 'auto'
                        || isNaN(areaSize)
                    ) {
                        lineWidth = gap;
                    }
                    else {
                        lineWidth = areaSize;
                    }
                    if (xStart == xEnd) {
                        // 纵向
K
kener 已提交
1086
                        if (Math.abs(this.component.grid.getX() - xStart) < 2) {
1087 1088 1089 1090
                            // 最左边
                            lineWidth /= 2;
                            xStart = xEnd = xEnd + lineWidth / 2;
                        }
K
kener 已提交
1091
                        else if (Math.abs(this.component.grid.getXend() - xStart) < 2) {
1092 1093 1094 1095 1096 1097 1098
                            // 最右边
                            lineWidth /= 2;
                            xStart = xEnd = xEnd - lineWidth / 2;
                        }
                    }
                    else if (yStart == yEnd) {
                        // 横向
K
kener 已提交
1099
                        if (Math.abs(this.component.grid.getY() - yStart) < 2) {
1100 1101 1102 1103
                            // 最上边
                            lineWidth /= 2;
                            yStart = yEnd = yEnd + lineWidth / 2;
                        }
K
kener 已提交
1104
                        else if (Math.abs(this.component.grid.getYend() - yStart) < 2) {
1105 1106 1107 1108 1109
                            // 最右边
                            lineWidth /= 2;
                            yStart = yEnd = yEnd - lineWidth / 2;
                        }
                    }
K
kener 已提交
1110
                    this._axisShadowShape.style = {
1111 1112 1113 1114 1115 1116 1117
                        xStart : xStart,
                        yStart : yStart,
                        xEnd : xEnd,
                        yEnd : yEnd,
                        strokeColor : areaColor,
                        lineWidth : lineWidth
                    };
K
kener 已提交
1118
                    this._axisShadowShape.invisible = false;
K
kener 已提交
1119
                    this.zr.modShape(this._axisShadowShape.id);
1120
                }
K
kener 已提交
1121
                this.zr.refresh();
1122
            }
K
kener 已提交
1123
        },
1124

K
kener 已提交
1125 1126 1127
        __onmousemove : function (param) {
            clearTimeout(this._hidingTicket);
            clearTimeout(this._showingTicket);
K
kener 已提交
1128
            var target = param.target;
K
kener 已提交
1129 1130 1131
            var mx = zrEvent.getX(param.event);
            var my = zrEvent.getY(param.event);
            if (!target) {
K
kener 已提交
1132
                // 判断是否落到直角系里,axis触发的tooltip
K
kener 已提交
1133 1134 1135 1136 1137 1138
                this._curTarget = false;
                this._event = param.event;
                this._event._target = this._event.target || this._event.toElement;
                this._event.zrenderX = mx;
                this._event.zrenderY = my;
                if (this._needAxisTrigger 
K
kener 已提交
1139
                    && this.component.grid 
K
kener 已提交
1140
                    && zrArea.isInside(
K
kener 已提交
1141
                        rectangleInstance,
K
kener 已提交
1142
                        this.component.grid.getArea(),
K
kener 已提交
1143 1144 1145 1146
                        mx,
                        my
                    )
                ) {
K
kener 已提交
1147
                    this._showingTicket = setTimeout(this._tryShow, this._showDelay);
K
kener 已提交
1148
                }
K
kener 已提交
1149
                else if (this._needAxisTrigger 
K
kener 已提交
1150 1151
                        && this.component.polar 
                        && this.component.polar.isInside([mx, my]) != -1
K
kener 已提交
1152
                ) {
K
kener 已提交
1153
                    this._showingTicket = setTimeout(this._tryShow, this._showDelay);
K
kener 已提交
1154 1155
                }
                else {
K
kener 已提交
1156
                    !this._event.connectTrigger && this.messageCenter.dispatch(
K
kener 已提交
1157
                        ecConfig.EVENT.TOOLTIP_OUT_GRID,
K
kener 已提交
1158
                        this._event
K
kener 已提交
1159
                    );
K
kener 已提交
1160
                    this._hidingTicket = setTimeout(this._hide, this._hideDelay);
K
kener 已提交
1161 1162 1163
                }
            }
            else {
K
kener 已提交
1164 1165 1166 1167 1168
                this._curTarget = target;
                this._event = param.event;
                this._event._target = this._event.target || this._event.toElement;
                this._event.zrenderX = mx;
                this._event.zrenderY = my;
K
kener 已提交
1169
                var polarIndex;
K
kener 已提交
1170
                if (this._needAxisTrigger 
K
kener 已提交
1171 1172
                    && this.component.polar 
                    && (polarIndex = this.component.polar.isInside([mx, my])) != -1
K
kener 已提交
1173 1174
                ) {
                    // 看用这个polar的系列数据是否是axis触发,如果是设置_curTarget为nul
K
kener 已提交
1175
                    var series = this.option.series;
K
kener 已提交
1176 1177
                    for (var i = 0, l = series.length; i < l; i++) {
                        if (series[i].polarIndex == polarIndex
K
kener 已提交
1178 1179
                            && this.deepQuery(
                                   [series[i], this.option], 'tooltip.trigger'
K
kener 已提交
1180 1181
                               ) == 'axis'
                        ) {
K
kener 已提交
1182
                            this._curTarget = null;
K
kener 已提交
1183 1184 1185 1186 1187
                            break;
                        }
                    }
                   
                }
K
kener 已提交
1188
                this._showingTicket = setTimeout(this._tryShow, this._showDelay);
K
kener 已提交
1189
            }
K
kener 已提交
1190
        },
K
kener 已提交
1191

1192 1193 1194
        /**
         * zrender事件响应:鼠标离开绘图区域
         */
K
kener 已提交
1195 1196 1197 1198 1199 1200
        __onglobalout : function () {
            clearTimeout(this._hidingTicket);
            clearTimeout(this._showingTicket);
            this._hidingTicket = setTimeout(this._hide, this._hideDelay);
        },
        
K
kener 已提交
1201 1202 1203
        /**
         * 异步回调填充内容
         */
K
kener 已提交
1204 1205
        _setContent : function (ticket, content) {
            if (!this._tDom) {
K
kener 已提交
1206 1207
                return;
            }
K
kener 已提交
1208 1209
            if (ticket == this._curTicket) {
                this._tDom.innerHTML = content;
K
kener 已提交
1210
            }
K
kener 已提交
1211
            
K
kener 已提交
1212 1213
            setTimeout(this._refixed, 20);
        },
K
kener 已提交
1214

K
kener 已提交
1215 1216 1217
        ontooltipHover : function (param, tipShape) {
            if (!this._lastTipShape // 不存在或者存在但dataIndex发生变化才需要重绘
                || (this._lastTipShape && this._lastTipShape.dataIndex != param.dataIndex)
K
kener 已提交
1218
            ) {
K
kener 已提交
1219 1220
                if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
                    this.zr.delShape(this._lastTipShape.tipShape);
K
kener 已提交
1221
                    this.shapeList.length = 2;
K
kener 已提交
1222 1223
                }
                for (var i = 0, l = tipShape.length; i < l; i++) {
K
kener 已提交
1224
                    tipShape[i].zlevel = this._zlevelBase;
K
kener 已提交
1225
                    tipShape[i].style = zrShapeBase.prototype.getHighlightStyle(
K
kener 已提交
1226 1227 1228 1229 1230 1231 1232 1233 1234
                        tipShape[i].style,
                        tipShape[i].highlightStyle
                    );
                    tipShape[i].draggable = false;
                    tipShape[i].hoverable = false;
                    tipShape[i].clickable = false;
                    tipShape[i].ondragend = null;
                    tipShape[i].ondragover = null;
                    tipShape[i].ondrop = null;
K
kener 已提交
1235
                    this.shapeList.push(tipShape[i]);
K
kener 已提交
1236
                    this.zr.addShape(tipShape[i]);
K
kener 已提交
1237
                }
K
kener 已提交
1238
                this._lastTipShape = {
K
kener 已提交
1239 1240 1241 1242
                    dataIndex : param.dataIndex,
                    tipShape : tipShape
                };
            }
K
kener 已提交
1243
        },
K
kener 已提交
1244
        
K
kener 已提交
1245 1246 1247
        ondragend : function () {
            this._hide();
        },
K
kener 已提交
1248 1249 1250 1251
        
        /**
         * 图例选择
         */
K
kener 已提交
1252 1253 1254
        onlegendSelected : function (param) {
            this._selectedMap = param.selected;
        },
K
kener 已提交
1255
        
K
kener 已提交
1256 1257 1258
        _setSelectedMap : function () {
            if (this.option.legend && this.option.legend.selected) {
                this._selectedMap = this.option.legend.selected;
K
kener 已提交
1259 1260
            }
            else {
K
kener 已提交
1261
                this._selectedMap = {};
K
kener 已提交
1262
            }
K
kener 已提交
1263
        },
K
kener 已提交
1264
        
K
kener 已提交
1265 1266 1267
        _isSelected : function (itemName) {
            if (typeof this._selectedMap[itemName] != 'undefined') {
                return this._selectedMap[itemName];
K
kener 已提交
1268 1269 1270 1271
            }
            else {
                return true; // 没在legend里定义的都为true啊~
            }
K
kener 已提交
1272
        },
K
kener 已提交
1273

K
kener 已提交
1274 1275 1276 1277 1278 1279
        /**
         * 模拟tooltip hover方法
         * {object} params  参数
         *          {seriesIndex: 0, seriesName:'', dataInex:0} line、bar、scatter、k、radar
         *          {seriesIndex: 0, seriesName:'', name:''} map、pie、chord
         */
K
kener 已提交
1280
        showTip : function (params) {
K
kener 已提交
1281 1282 1283 1284 1285
            if (!params) {
                return;
            }
            
            var seriesIndex;
K
kener 已提交
1286
            var series = this.option.series;
K
kener 已提交
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
            if (typeof params.seriesIndex != 'undefined') {
                seriesIndex = params.seriesIndex;
            }
            else {
                var seriesName = params.seriesName;
                for (var i = 0, l = series.length; i < l; i++) {
                    if (series[i].name == seriesName) {
                        seriesIndex = i;
                        break;
                    }
                }
            }
            
            var serie = series[seriesIndex];
            if (typeof serie == 'undefined') {
                return;
            }
            var chart = myChart.chart[serie.type];
K
kener 已提交
1305 1306
            var isAxisTrigger = this.deepQuery(
                                    [serie, this.option], 'tooltip.trigger'
K
kener 已提交
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
                                ) == 'axis';
            
            if (!chart) {
                return;
            }
            
            if (isAxisTrigger) {
                // axis trigger
                var dataIndex = params.dataIndex;
                switch (chart.type) {
                    case ecConfig.CHART_TYPE_LINE :
                    case ecConfig.CHART_TYPE_BAR :
                    case ecConfig.CHART_TYPE_K :
K
kener 已提交
1320 1321
                        if (typeof this.component.xAxis == 'undefined' 
                            || typeof this.component.yAxis == 'undefined'
K
kener 已提交
1322 1323 1324 1325 1326 1327
                            || serie.data.length <= dataIndex
                        ) {
                            return;
                        }
                        var xAxisIndex = serie.xAxisIndex || 0;
                        var yAxisIndex = serie.yAxisIndex || 0;
K
kener 已提交
1328
                        if (this.component.xAxis.getAxis(xAxisIndex).type 
K
kener 已提交
1329 1330 1331
                            == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                        ) {
                            // 横轴是类目
K
kener 已提交
1332
                            this._event = {
K
kener 已提交
1333 1334 1335 1336 1337 1338
                                zrenderX : this.component.xAxis.getAxis(xAxisIndex)
                                           .getCoordByIndex(dataIndex),
                                zrenderY : this.component.grid.getY() 
                                           + (this.component.grid.getYend() 
                                              - this.component.grid.getY()
                                             ) / 4
K
kener 已提交
1339 1340 1341 1342
                            };
                        }
                        else {
                            // 纵轴是类目
K
kener 已提交
1343
                            this._event = {
K
kener 已提交
1344 1345 1346 1347 1348 1349
                                zrenderX : this.component.grid.getX() 
                                           + (this.component.grid.getXend() 
                                              - this.component.grid.getX()
                                             ) / 4,
                                zrenderY : this.component.yAxis.getAxis(yAxisIndex)
                                           .getCoordByIndex(dataIndex)
K
kener 已提交
1350 1351
                            };
                        }
K
kener 已提交
1352
                        this._showAxisTrigger(
K
kener 已提交
1353 1354 1355 1356 1357 1358
                            xAxisIndex, 
                            yAxisIndex,
                            dataIndex
                        );
                        break;
                    case ecConfig.CHART_TYPE_RADAR :
K
kener 已提交
1359
                        if (typeof this.component.polar == 'undefined' 
K
kener 已提交
1360 1361 1362 1363 1364
                            || serie.data[0].value.length <= dataIndex
                        ) {
                            return;
                        }
                        var polarIndex = serie.polarIndex || 0;
K
kener 已提交
1365 1366 1367
                        var vector = this.component.polar.getVector(
                            polarIndex, dataIndex, 'max'
                        );
K
kener 已提交
1368
                        this._event = {
K
kener 已提交
1369 1370 1371
                            zrenderX : vector[0],
                            zrenderY : vector[1]
                        };
K
kener 已提交
1372
                        this._showPolarTrigger(
K
kener 已提交
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
                            polarIndex, 
                            dataIndex
                        );
                        break;
                }
            }
            else {
                // item trigger
                var shapeList = chart.shapeList;
                var x;
                var y;
                switch (chart.type) {
                    case ecConfig.CHART_TYPE_LINE :
                    case ecConfig.CHART_TYPE_BAR :
                    case ecConfig.CHART_TYPE_K :
                    case ecConfig.CHART_TYPE_SCATTER :
                        var dataIndex = params.dataIndex;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
                            if (ecData.get(shapeList[i], 'seriesIndex') == seriesIndex
                                && ecData.get(shapeList[i], 'dataIndex') == dataIndex
                            ) {
K
kener 已提交
1394
                                this._curTarget = shapeList[i];
K
kener 已提交
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
                                x = shapeList[i].style.x;
                                y = chart.type != ecConfig.CHART_TYPE_K 
                                    ? shapeList[i].style.y : shapeList[i].style.y[0];
                                break;
                            }
                        }
                        break;
                    case ecConfig.CHART_TYPE_RADAR :
                        var dataIndex = params.dataIndex;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
K
kener 已提交
1405
                            if (shapeList[i].type == 'polygon'
K
kener 已提交
1406 1407 1408
                                && ecData.get(shapeList[i], 'seriesIndex') == seriesIndex
                                && ecData.get(shapeList[i], 'dataIndex') == dataIndex
                            ) {
K
kener 已提交
1409
                                this._curTarget = shapeList[i];
K
kener 已提交
1410 1411 1412
                                var vector = this.component.polar.getCenter(
                                    serie.polarIndex || 0
                                );
K
kener 已提交
1413 1414 1415 1416 1417 1418 1419 1420 1421
                                x = vector[0];
                                y = vector[1];
                                break;
                            }
                        }
                        break;
                    case ecConfig.CHART_TYPE_PIE :
                        var name = params.name;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
K
kener 已提交
1422
                            if (shapeList[i].type == 'sector'
K
kener 已提交
1423 1424 1425
                                && ecData.get(shapeList[i], 'seriesIndex') == seriesIndex
                                && ecData.get(shapeList[i], 'name') == name
                            ) {
K
kener 已提交
1426 1427
                                this._curTarget = shapeList[i];
                                var style = this._curTarget.style;
K
kener 已提交
1428 1429
                                var midAngle = (style.startAngle + style.endAngle) 
                                                / 2 * Math.PI / 180;
K
kener 已提交
1430 1431
                                x = this._curTarget.style.x + Math.cos(midAngle) * style.r / 1.5;
                                y = this._curTarget.style.y - Math.sin(midAngle) * style.r / 1.5;
K
kener 已提交
1432 1433 1434 1435 1436 1437 1438 1439
                                break;
                            }
                        }
                        break;
                    case ecConfig.CHART_TYPE_MAP :
                        var name = params.name;
                        var mapType = serie.mapType;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
K
kener 已提交
1440
                            if (shapeList[i].type == 'text'
K
kener 已提交
1441
                                && shapeList[i]._mapType == mapType
K
kener 已提交
1442
                                && shapeList[i].style._name == name
K
kener 已提交
1443
                            ) {
K
kener 已提交
1444 1445 1446
                                this._curTarget = shapeList[i];
                                x = this._curTarget.style.x + this._curTarget.position[0];
                                y = this._curTarget.style.y + this._curTarget.position[1];
K
kener 已提交
1447 1448 1449 1450 1451 1452 1453
                                break;
                            }
                        }
                        break;
                    case ecConfig.CHART_TYPE_CHORD:
                        var name = params.name;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
K
kener 已提交
1454
                            if (shapeList[i].type == 'sector'
K
kener 已提交
1455 1456
                                && ecData.get(shapeList[i], 'name') == name
                            ) {
K
kener 已提交
1457 1458
                                this._curTarget = shapeList[i];
                                var style = this._curTarget.style;
K
kener 已提交
1459 1460
                                var midAngle = (style.startAngle + style.endAngle) 
                                                / 2 * Math.PI / 180;
K
kener 已提交
1461 1462 1463
                                x = this._curTarget.style.x + Math.cos(midAngle) * (style.r - 2);
                                y = this._curTarget.style.y - Math.sin(midAngle) * (style.r - 2);
                                this.zr.trigger(
K
kener 已提交
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
                                    zrConfig.EVENT.MOUSEMOVE,
                                    {
                                        zrenderX : x,
                                        zrenderY : y
                                    }
                                );
                                return;
                            }
                        }
                        break;
                    case ecConfig.CHART_TYPE_FORCE:
                        var name = params.name;
                        for (var i = 0, l = shapeList.length; i < l; i++) {
K
kener 已提交
1477
                            if (shapeList[i].type == 'circle'
K
kener 已提交
1478 1479
                                && ecData.get(shapeList[i], 'name') == name
                            ) {
K
kener 已提交
1480 1481 1482
                                this._curTarget = shapeList[i];
                                x = this._curTarget.position[0];
                                y = this._curTarget.position[1];
K
kener 已提交
1483 1484 1485 1486 1487 1488
                                break;
                            }
                        }
                        break;
                }
                if (typeof x != 'undefined' && typeof y != 'undefined') {
K
kener 已提交
1489
                    this._event = {
K
kener 已提交
1490 1491 1492
                        zrenderX : x,
                        zrenderY : y
                    };
K
kener 已提交
1493 1494 1495
                    this.zr.addHoverShape(this._curTarget);
                    this.zr.refreshHover();
                    this._showItemTrigger();
K
kener 已提交
1496 1497
                }
            }
K
kener 已提交
1498
        },
K
kener 已提交
1499 1500 1501 1502
        
        /**
         * 关闭,公开接口 
         */
K
kener 已提交
1503 1504 1505
        hideTip : function () {
            this._hide();
        },
K
kener 已提交
1506
        
K
kener 已提交
1507 1508 1509 1510 1511 1512 1513
        /**
         * 刷新
         */
        refresh : function (newOption) {
            // this._selectedMap;
            // this._defaultCssText;    // css样式缓存
            // this._needAxisTrigger;   // 坐标轴触发
K
kener 已提交
1514 1515
            // this._curTarget;
            // this._event;
K
kener 已提交
1516 1517
            // this._curTicket;         // 异步回调标识,用来区分多个请求
            
K
kener 已提交
1518 1519 1520
            // 缓存一些高宽数据
            this._zrHeight = this.zr.getHeight();
            this._zrWidth = this.zr.getWidth();
K
kener 已提交
1521 1522 1523 1524
            
            if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
                this.zr.delShape(this._lastTipShape.tipShape);
            }
K
kener 已提交
1525
            this._lastTipShape = false;
K
kener 已提交
1526
            this.shapeList.length = 2;
K
kener 已提交
1527
            
K
kener 已提交
1528
            if (newOption) {
K
kener 已提交
1529 1530 1531 1532 1533
                this.option = newOption;
                this.option.tooltip = this.reformOption(this.option.tooltip);
                this.option.tooltip.textStyle = zrUtil.merge(
                    this.option.tooltip.textStyle,
                    this.ecTheme.textStyle
K
kener 已提交
1534 1535
                );
                // 补全padding属性
K
kener 已提交
1536 1537
                this.option.tooltip.padding = this.reformCssArray(
                    this.option.tooltip.padding
K
kener 已提交
1538
                );
K
kener 已提交
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
    
                this._needAxisTrigger = false;
                if (this.option.tooltip.trigger == 'axis') {
                    this._needAxisTrigger = true;
                }
    
                var series = this.option.series;
                for (var i = 0, l = series.length; i < l; i++) {
                    if (this.query(series[i], 'tooltip.trigger') == 'axis') {
                        this._needAxisTrigger = true;
                        break;
                    }
                }
                // this._hidingTicket;
                // this._showingTicket;
                this._showDelay = this.option.tooltip.showDelay; // 显示延迟
                this._hideDelay = this.option.tooltip.hideDelay; // 隐藏延迟
                this._defaultCssText = this._style(this.option.tooltip);
                
K
kener 已提交
1558 1559
                this._setSelectedMap();
                this._axisLineWidth = this.option.tooltip.axisPointer.lineStyle.width;
K
kener 已提交
1560
            }
K
kener 已提交
1561 1562 1563
            if (this.showing) {
                this._tryShow();
            }
K
kener 已提交
1564
        },
K
kener 已提交
1565 1566 1567 1568

        /**
         * 释放后实例不可用,重载基类方法
         */
K
kener 已提交
1569
        dispose : function () {
K
kener 已提交
1570 1571 1572 1573
            if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
                this.zr.delShape(this._lastTipShape.tipShape);
            }
            this.clear();
K
kener 已提交
1574
            this.shapeList = null;
K
kener 已提交
1575
            
K
kener 已提交
1576 1577 1578 1579
            clearTimeout(this._hidingTicket);
            clearTimeout(this._showingTicket);
            this.zr.un(zrConfig.EVENT.MOUSEMOVE, self._onmousemove);
            this.zr.un(zrConfig.EVENT.GLOBALOUT, self._onglobalout);
K
kener 已提交
1580
            
K
kener 已提交
1581 1582
            if (this.hasAppend) {
                this.dom.firstChild.removeChild(this._tDom);
K
kener 已提交
1583
            }
K
kener 已提交
1584 1585
            this._tDom = null;
        },
K
kener 已提交
1586 1587 1588 1589
        
        /**
         * html转码的方法
         */
K
kener 已提交
1590
        _encodeHTML : function (source) {
K
kener 已提交
1591
            return String(source)
K
kener 已提交
1592 1593 1594 1595 1596
                        .replace(/&/g, '&amp;')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;')
                        .replace(/"/g, '&quot;')
                        .replace(/'/g, '&#39;');
K
kener 已提交
1597
        }
K
kener 已提交
1598 1599 1600 1601
    };
    
    zrUtil.inherits(Tooltip, Base);
    
1602 1603
    require('../component').define('tooltip', Tooltip);

K
kener 已提交
1604 1605
    return Tooltip;
});