line.js 39.4 KB
Newer Older
K
kener 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
 * echarts图表类:折线图
 *
 * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, linzhifeng@baidu.com)
 *
 */
define(function(require) {
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} series 数据
     * @param {Object} component 组件
     */
K
kener 已提交
16
    function Line(ecConfig, messageCenter, zr, option, component){
K
kener 已提交
17 18
        // 基类装饰
        var ComponentBase = require('../component/base');
K
kener 已提交
19
        ComponentBase.call(this, ecConfig, zr);
K
kener 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32
        // 可计算特性装饰
        var CalculableBase = require('./calculableBase');
        CalculableBase.call(this, zr, option);

        var zrColor = require('zrender/tool/color');

        var self = this;
        self.type = ecConfig.CHART_TYPE_LINE;

        var series;                 // 共享数据源,不要修改跟自己无关的项

        var _zlevelBase = self.getZlevelBase();

K
kener 已提交
33
        var finalPLMap = {}; // 完成的point list(PL)
K
kener 已提交
34
        var _sIndex2ColorMap = {};  // series默认颜色索引,seriesIndex索引到color
K
kener 已提交
35
        var _symbol = ecConfig.symbolList;
K
kener 已提交
36 37
        var _sIndex2ShapeMap = {};  // series拐点图形类型,seriesIndex索引到shape type

38 39 40 41
        require('zrender/shape').get('icon').define(
            'legendLineIcon', legendLineIcon
        );
        
K
kener 已提交
42
        function _buildShape() {
K
kener 已提交
43
            finalPLMap = {};
K
kener 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57
            self.selectedMap = {};

            // 水平垂直双向series索引 ,position索引到seriesIndex
            var _position2sIndexMap = {
                top : [],
                bottom : [],
                left : [],
                right : []
            };
            var xAxisIndex;
            var yAxisIndex;
            var xAxis;
            var yAxis;
            for (var i = 0, l = series.length; i < l; i++) {
K
kener 已提交
58
                if (series[i].type == self.type) {
K
kener 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
                    series[i] = self.reformOption(series[i]);
                    xAxisIndex = series[i].xAxisIndex;
                    yAxisIndex = series[i].yAxisIndex;
                    xAxis = component.xAxis.getAxis(xAxisIndex);
                    yAxis = component.yAxis.getAxis(yAxisIndex);
                    if (xAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                    ) {
                        _position2sIndexMap[xAxis.getPosition()].push(i);
                    }
                    else if (yAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
                    ) {
                        _position2sIndexMap[yAxis.getPosition()].push(i);
                    }
                }
            }
            //console.log(_position2sIndexMap)
            for (var position in _position2sIndexMap) {
                if (_position2sIndexMap[position].length > 0) {
                    _buildSinglePosition(
                        position, _position2sIndexMap[position]
                    );
                }
            }

            for (var i = 0, l = self.shapeList.length; i < l; i++) {
                self.shapeList[i].id = zr.newShapeId(self.type);
                zr.addShape(self.shapeList[i]);
            }
        }

        /**
         * 构建单个方向上的折线图
         *
         * @param {number} seriesIndex 系列索引
         */
        function _buildSinglePosition(position, seriesArray) {
            var mapData = _mapData(seriesArray);
            var locationMap = mapData.locationMap;
            var maxDataLength = mapData.maxDataLength;

            if (maxDataLength === 0 || locationMap.length === 0) {
                return;
            }

            switch (position) {
                case 'bottom' :
                case 'top' :
                    _buildHorizontal(maxDataLength, locationMap);
                    break;
                case 'left' :
                case 'right' :
                    _buildVertical(maxDataLength, locationMap);
                    break;
            }
K
kener 已提交
113 114 115 116 117 118 119
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                self.buildMark(
                    series[seriesArray[i]],
                    seriesArray[i],
                    component
                );
            }
K
kener 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        }

        /**
         * 数据整形
         * 数组位置映射到系列索引
         */
        function _mapData(seriesArray) {
            var serie;                              // 临时映射变量
            var dataIndex = 0;                      // 堆叠数据所在位置映射
            var stackMap = {};                      // 堆叠数据位置映射,堆叠组在二维中的第几项
            var magicStackKey = '__kener__stack__'; // 堆叠命名,非堆叠数据安单一堆叠处理
            var stackKey;                           // 临时映射变量
            var serieName;                          // 临时映射变量
            var legend = component.legend;
            var locationMap = [];                   // 需要返回的东西:数组位置映射到系列索引
            var maxDataLength = 0;                  // 需要返回的东西:最大数据长度
136
            var iconShape;
K
kener 已提交
137 138 139 140
            // 计算需要显示的个数和分配位置并记在下面这个结构里
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                serie = series[seriesArray[i]];
                serieName = serie.name;
141 142 143
                
                _sIndex2ShapeMap[seriesArray[i]]
                    = _sIndex2ShapeMap[seriesArray[i]]
144
                      || self.query(serie,'symbol')
145 146
                      || _symbol[i % _symbol.length];
                      
K
kener 已提交
147 148
                if (legend){
                    self.selectedMap[serieName] = legend.isSelected(serieName);
149
                    
K
kener 已提交
150 151
                    _sIndex2ColorMap[seriesArray[i]]
                        = legend.getColor(serieName);
152 153 154 155 156 157 158 159
                        
                    iconShape = legend.getItemShape(serieName);
                    if (iconShape) {
                        // 回调legend,换一个更形象的icon
                        iconShape.shape = 'icon';
                        iconShape.style.iconType = 'legendLineIcon';
                        iconShape.style.symbol = 
                            _sIndex2ShapeMap[seriesArray[i]];
K
kener 已提交
160
                        
161 162
                        legend.setItemShape(serieName, iconShape);
                    }
K
kener 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
                } else {
                    self.selectedMap[serieName] = true;
                    _sIndex2ColorMap[seriesArray[i]]
                        = zr.getColor(seriesArray[i]);
                }

                if (self.selectedMap[serieName]) {
                    stackKey = serie.stack || (magicStackKey + seriesArray[i]);
                    if (typeof stackMap[stackKey] == 'undefined') {
                        stackMap[stackKey] = dataIndex;
                        locationMap[dataIndex] = [seriesArray[i]];
                        dataIndex++;
                    }
                    else {
                        // 已经分配了位置就推进去就行
                        locationMap[stackMap[stackKey]].push(seriesArray[i]);
                    }
                }
                // 兼职帮算一下最大长度
                maxDataLength = Math.max(maxDataLength, serie.data.length);
            }
            /* 调试输出
            var s = '';
            for (var i = 0, l = maxDataLength; i < l; i++) {
                s = '[';
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    s +='['
                    for (var m = 0, n = locationMap[j].length - 1; m < n; m++) {
                        s += series[locationMap[j][m]].data[i] + ','
                    }
                    s += series[locationMap[j][locationMap[j].length - 1]]
                         .data[i];
                    s += ']'
                }
                s += ']';
                console.log(s);
            }
            console.log(locationMap)
            */

            return {
                locationMap : locationMap,
                maxDataLength : maxDataLength
            };
        }

        /**
         * 构建类目轴为水平方向的折线图系列
         */
        function _buildHorizontal(maxDataLength, locationMap) {
            // 确定类目轴和数值轴,同一方向随便找一个即可
            var seriesIndex = locationMap[0][0];
            var serie = series[seriesIndex];
            var xAxisIndex = serie.xAxisIndex;
            var categoryAxis = component.xAxis.getAxis(xAxisIndex);
            var yAxisIndex; // 数值轴各异
            var valueAxis;  // 数值轴各异

            var x;
            var y;
            var lastYP; // 正向堆叠处理
            var baseYP;
            var lastYN; // 负向堆叠处理
            var baseYN;
K
kener 已提交
227
            //var finalPLMap = {}; // 完成的point list(PL)
K
kener 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
            var curPLMap = {};   // 正在记录的point list(PL)
            var data;
            var value;
            for (var i = 0, l = maxDataLength; i < l; i++) {
                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {
                    // 系列数据超出类目轴长度
                    break;
                }
                x = categoryAxis.getCoordByIndex(i);
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    // 堆叠数据用第一条valueAxis
                    yAxisIndex = series[locationMap[j][0]].yAxisIndex || 0;
                    valueAxis = component.yAxis.getAxis(yAxisIndex);
                    baseYP = lastYP = baseYN = lastYN = valueAxis.getCoord(0);
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        curPLMap[seriesIndex] = curPLMap[seriesIndex] || [];
                        if (value == '-') {
                            // 空数据则把正在记录的curPLMap添加到finalPLMap中
                            if (curPLMap[seriesIndex].length > 0) {
                                finalPLMap[seriesIndex] =
                                    finalPLMap[seriesIndex] || [];

                                finalPLMap[seriesIndex].push(
                                    curPLMap[seriesIndex]
                                );

                                curPLMap[seriesIndex] = [];
                            }
                            continue;
                        }
                        y = valueAxis.getCoord(value);
                        if (value >= 0) {
                            // 正向堆叠
                            lastYP -= (baseYP - y);
                            y = lastYP;
                        }
                        else if (value < 0){
                            // 负向堆叠
                            lastYN += y - baseYN;
                            y = lastYN;
                        }
                        curPLMap[seriesIndex].push(
                            [x, y, i, categoryAxis.getNameByIndex(i), x, baseYP]
                        );
                    }
                }
                // 补充空数据的拖拽提示
                lastYP = component.grid.getY();
K
kener 已提交
284
                var symbolSize;
K
kener 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value != '-') {
                            // 只关心空数据
                            continue;
                        }
                        if (self.deepQuery(
                                [data, serie, option], 'calculable'
                            )
                        ) {
K
kener 已提交
303
                            symbolSize = self.deepQuery(
K
kener 已提交
304
                                [data, serie],
K
kener 已提交
305
                                'symbolSize'
K
kener 已提交
306
                            );
K
kener 已提交
307
                            lastYP += symbolSize * 2 + 5;
K
kener 已提交
308 309 310
                            y = lastYP;
                            self.shapeList.push(_getCalculableItem(
                                seriesIndex, i, categoryAxis.getNameByIndex(i),
K
kener 已提交
311
                                x, y, 'horizontal'
K
kener 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
                            ));
                        }
                    }
                }
            }

            // 把剩余未完成的curPLMap全部添加到finalPLMap中
            for (var sId in curPLMap) {
                if (curPLMap[sId].length > 0) {
                    finalPLMap[sId] = finalPLMap[sId] || [];
                    finalPLMap[sId].push(curPLMap[sId]);
                    curPLMap[sId] = [];
                }
            }
            _buildBorkenLine(finalPLMap, categoryAxis, 'horizontal');
        }

        /**
         * 构建类目轴为垂直方向的折线图系列
         */
        function _buildVertical(maxDataLength, locationMap) {
            // 确定类目轴和数值轴,同一方向随便找一个即可
            var seriesIndex = locationMap[0][0];
            var serie = series[seriesIndex];
            var yAxisIndex = serie.yAxisIndex;
            var categoryAxis = component.yAxis.getAxis(yAxisIndex);
            var xAxisIndex; // 数值轴各异
            var valueAxis;  // 数值轴各异

            var x;
            var y;
            var lastXP; // 正向堆叠处理
            var baseXP;
            var lastXN; // 负向堆叠处理
            var baseXN;
K
kener 已提交
347
            //var finalPLMap = {}; // 完成的point list(PL)
K
kener 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
            var curPLMap = {};   // 正在记录的point list(PL)
            var data;
            var value;
            for (var i = 0, l = maxDataLength; i < l; i++) {
                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {
                    // 系列数据超出类目轴长度
                    break;
                }
                y = categoryAxis.getCoordByIndex(i);
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    // 堆叠数据用第一条valueAxis
                    xAxisIndex = series[locationMap[j][0]].xAxisIndex || 0;
                    valueAxis = component.xAxis.getAxis(xAxisIndex);
                    baseXP = lastXP = baseXN = lastXN = valueAxis.getCoord(0);
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        curPLMap[seriesIndex] = curPLMap[seriesIndex] || [];
                        if (value == '-') {
                            // 空数据则把正在记录的curPLMap添加到finalPLMap中
                            if (curPLMap[seriesIndex].length > 0) {
                                finalPLMap[seriesIndex] =
                                    finalPLMap[seriesIndex] || [];

                                finalPLMap[seriesIndex].push(
                                    curPLMap[seriesIndex]
                                );

                                curPLMap[seriesIndex] = [];
                            }
                            continue;
                        }
                        x = valueAxis.getCoord(value);
                        if (value >= 0) {
                            // 正向堆叠
                            lastXP += x - baseXP;
                            x = lastXP;
                        }
                        else if (value < 0){
                            // 负向堆叠
                            lastXN -= baseXN - x;
                            x = lastXN;
                        }
                        curPLMap[seriesIndex].push(
                            [x, y, i, categoryAxis.getNameByIndex(i), baseXP, y]
                        );
                    }
                }
                // 补充空数据的拖拽提示
                lastXP = component.grid.getXend();
K
kener 已提交
404
                var symbolSize;
K
kener 已提交
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
                for (var j = 0, k = locationMap.length; j < k; j++) {
                    for (var m = 0, n = locationMap[j].length; m < n; m++) {
                        seriesIndex = locationMap[j][m];
                        serie = series[seriesIndex];
                        data = serie.data[i];
                        value = typeof data != 'undefined'
                                ? (typeof data.value != 'undefined'
                                  ? data.value
                                  : data)
                                : '-';
                        if (value != '-') {
                            // 只关心空数据
                            continue;
                        }
                        if (self.deepQuery(
                                [data, serie, option], 'calculable'
                            )
                        ) {
K
kener 已提交
423
                            symbolSize = self.deepQuery(
K
kener 已提交
424
                                [data, serie],
K
kener 已提交
425
                                'symbolSize'
K
kener 已提交
426
                            );
K
kener 已提交
427
                            lastXP -= symbolSize * 2 + 5;
K
kener 已提交
428 429 430
                            x = lastXP;
                            self.shapeList.push(_getCalculableItem(
                                seriesIndex, i, categoryAxis.getNameByIndex(i),
K
kener 已提交
431
                                x, y, 'vertical'
K
kener 已提交
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
                            ));
                        }
                    }
                }
            }

            // 把剩余未完成的curPLMap全部添加到finalPLMap中
            for (var sId in curPLMap) {
                if (curPLMap[sId].length > 0) {
                    finalPLMap[sId] = finalPLMap[sId] || [];
                    finalPLMap[sId].push(curPLMap[sId]);
                    curPLMap[sId] = [];
                }
            }
            _buildBorkenLine(finalPLMap, categoryAxis, 'vertical');
        }

        /**
         * 生成折线和折线上的拐点
         */
        function _buildBorkenLine(pointList, categoryAxis, orient) {
            var defaultColor;

            // 折线相关
            var lineWidth;
            var lineType;
K
kener 已提交
458
            var lineColor;
K
kener 已提交
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
            var normalColor;

            // 填充相关
            var isFill;
            var fillNormalColor;

            var serie;
            var data;
            var seriesPL;
            var singlePL;

            // 堆叠层叠需求,反顺序构建
            for (var seriesIndex = series.length - 1;
                seriesIndex >= 0;
                seriesIndex--
            ) {
                serie = series[seriesIndex];
                seriesPL = pointList[seriesIndex];
K
kener 已提交
477
                if (serie.type == self.type && typeof seriesPL != 'undefined') {
K
kener 已提交
478 479
                    defaultColor = _sIndex2ColorMap[seriesIndex];
                    // 多级控制
K
kener 已提交
480 481
                    lineWidth = self.query(
                        serie, 'itemStyle.normal.lineStyle.width'
K
kener 已提交
482
                    );
K
kener 已提交
483 484
                    lineType = self.query(
                        serie, 'itemStyle.normal.lineStyle.type'
K
kener 已提交
485
                    );
K
kener 已提交
486 487
                    lineColor = self.query(
                        serie, 'itemStyle.normal.lineStyle.color'
K
kener 已提交
488
                    );
K
kener 已提交
489 490
                    normalColor = self.getItemStyleColor(
                        self.query(serie, 'itemStyle.normal.color'), seriesIndex, -1
K
kener 已提交
491 492
                    );

K
kener 已提交
493 494
                    isFill = typeof self.query(
                        serie, 'itemStyle.normal.areaStyle'
K
kener 已提交
495 496
                    ) != 'undefined';

K
kener 已提交
497 498
                    fillNormalColor = self.query(
                        serie, 'itemStyle.normal.areaStyle.color'
K
kener 已提交
499 500 501 502 503 504
                    );

                    for (var i = 0, l = seriesPL.length; i < l; i++) {
                        singlePL = seriesPL[i];
                        for (var j = 0, k = singlePL.length; j < k; j++) {
                            data = serie.data[singlePL[j][2]];
K
kener 已提交
505 506 507 508 509 510 511 512 513
                            if (self.deepQuery(
                                    [data, serie], 'showAllSymbol'
                                ) // 全显示
                                || (categoryAxis.isMainAxis(singlePL[j][2])
                                    && self.deepQuery(
                                           [data, serie], 'symbol'
                                       ) != 'none'
                                   ) // 主轴非空
                                || self.deepQuery(
K
kener 已提交
514 515
                                        [data, serie, option],
                                        'calculable'
K
kener 已提交
516
                                   ) // 可计算
K
kener 已提交
517
                            ) {
K
kener 已提交
518
                                self.shapeList.push(_getSymbol(
K
kener 已提交
519 520 521 522 523
                                    seriesIndex,
                                    singlePL[j][2], // dataIndex
                                    singlePL[j][3], // name
                                    singlePL[j][0], // x
                                    singlePL[j][1], // y
K
kener 已提交
524
                                    orient
K
kener 已提交
525 526 527 528
                                ));
                            }

                        }
K
kener 已提交
529 530 531 532 533
                        // 折线图
                        self.shapeList.push({
                            shape : 'brokenLine',
                            zlevel : _zlevelBase,
                            style : {
K
kener 已提交
534
                                miterLimit: lineWidth,
K
kener 已提交
535
                                pointList : singlePL,
K
kener 已提交
536 537 538
                                strokeColor : lineColor
                                              || normalColor 
                                              || defaultColor,
K
kener 已提交
539 540
                                lineWidth : lineWidth,
                                lineType : lineType,
K
kener 已提交
541
                                smooth : _getSmooth(serie.smooth),
K
kener 已提交
542 543
                                shadowColor : self.query(
                                  serie,
K
kener 已提交
544 545
                                  'itemStyle.normal.lineStyle.shadowColor'
                                ),
K
kener 已提交
546 547
                                shadowBlur: self.query(
                                  serie,
K
kener 已提交
548 549
                                  'itemStyle.normal.lineStyle.shadowBlur'
                                ),
K
kener 已提交
550 551
                                shadowOffsetX: self.query(
                                  serie,
K
kener 已提交
552 553
                                  'itemStyle.normal.lineStyle.shadowOffsetX'
                                ),
K
kener 已提交
554 555
                                shadowOffsetY: self.query(
                                  serie,
K
kener 已提交
556 557 558 559 560 561 562 563 564
                                  'itemStyle.normal.lineStyle.shadowOffsetY'
                                )
                            },
                            hoverable : false,
                            _main : true,
                            _seriesIndex : seriesIndex,
                            _orient : orient
                        });
                        
K
kener 已提交
565 566
                        if (isFill) {
                            self.shapeList.push({
K
kener 已提交
567
                                shape : 'halfSmoothPolygon',
K
kener 已提交
568 569
                                zlevel : _zlevelBase,
                                style : {
K
kener 已提交
570
                                    miterLimit: lineWidth,
K
kener 已提交
571 572 573 574 575 576 577 578 579 580 581
                                    pointList : singlePL.concat([
                                        [
                                            singlePL[singlePL.length - 1][4],
                                            singlePL[singlePL.length - 1][5] - 2
                                        ],
                                        [
                                            singlePL[0][4],
                                            singlePL[0][5] - 2
                                        ]
                                    ]),
                                    brushType : 'fill',
K
kener 已提交
582
                                    smooth : _getSmooth(serie.smooth),
K
kener 已提交
583 584
                                    color : fillNormalColor
                                            ? fillNormalColor
K
kener 已提交
585
                                            : zrColor.alpha(defaultColor,0.5)
K
kener 已提交
586 587 588
                                },
                                hoverable : false,
                                _main : true,
K
kener 已提交
589
                                _seriesIndex : seriesIndex,
K
kener 已提交
590 591 592 593
                                _orient : orient
                            });
                        }
                    }
K
kener 已提交
594
                }
K
kener 已提交
595 596
            }
        }
K
kener 已提交
597 598 599 600 601 602 603 604 605 606 607 608
        
        function _getSmooth(isSmooth/*, pointList, orient*/) {
            if (isSmooth) {
                /* 不科学啊,发现0.3通用了
                var delta;
                if (orient == 'horizontal') {
                    delta = Math.abs(pointList[0][0] - pointList[1][0]);
                }
                else {
                    delta = Math.abs(pointList[0][1] - pointList[1][1]);
                }
                */
K
kener 已提交
609
                return 0.3;
K
kener 已提交
610 611 612 613 614
            }
            else {
                return 0;
            }
        }
K
kener 已提交
615 616 617 618

        /**
         * 生成空数据所需的可计算提示图形
         */
K
kener 已提交
619 620 621
        function _getCalculableItem(
            seriesIndex, dataIndex, name, x, y, orient
        ) {
K
kener 已提交
622 623 624
            var color = series[seriesIndex].calculableHolderColor
                        || ecConfig.calculableHolderColor;

K
kener 已提交
625
            var itemShape = _getSymbol(
K
kener 已提交
626
                seriesIndex, dataIndex, name,
K
kener 已提交
627
                x, y, orient
K
kener 已提交
628
            );
K
kener 已提交
629 630 631
            itemShape.style.color = color;
            itemShape.style.strokeColor = color;
            itemShape.rotation = [0,0];
K
kener 已提交
632 633
            itemShape.hoverable = false;
            itemShape.draggable = false;
K
kener 已提交
634
            itemShape.style.text = undefined;
K
kener 已提交
635 636 637 638 639 640 641

            return itemShape;
        }

        /**
         * 生成折线图上的拐点图形
         */
K
kener 已提交
642
        function _getSymbol(seriesIndex, dataIndex, name, x, y, orient) {
K
kener 已提交
643 644
            var serie = series[seriesIndex];
            var data = serie.data[dataIndex];
K
kener 已提交
645
            
K
kener 已提交
646 647 648 649 650 651 652 653 654
            var itemShape = self.getSymbolShape(
                serie, seriesIndex, data, dataIndex, name, 
                x, y,
                _sIndex2ShapeMap[seriesIndex], 
                _sIndex2ColorMap[seriesIndex],
                '#fff',
                orient == 'vertical' ? 'horizontal' : 'vertical' // 翻转
            );
            itemShape.zlevel = _zlevelBase + 1;
655
            
K
kener 已提交
656 657 658 659
            if (self.deepQuery([data, serie, option], 'calculable')) {
                self.setCalculable(itemShape);
                itemShape.draggable = true;
            }
K
kener 已提交
660
            
K
kener 已提交
661 662 663
            return itemShape;
        }

K
kener 已提交
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
        // 位置转换
        function getMarkCoord(serie, seriesIndex, mpData) {
            var xAxis = component.xAxis.getAxis(serie.xAxisIndex);
            var yAxis = component.yAxis.getAxis(serie.yAxisIndex);
            
            return [
                typeof mpData.xAxis != 'string' 
                && xAxis.getCoordByIndex
                ? xAxis.getCoordByIndex(mpData.xAxis || 0)
                : xAxis.getCoord(mpData.xAxis || 0),
                
                typeof mpData.yAxis != 'string' 
                && yAxis.getCoordByIndex
                ? yAxis.getCoordByIndex(mpData.yAxis || 0)
                : yAxis.getCoord(mpData.yAxis || 0)
            ];
K
kener 已提交
680 681
        }
        
K
kener 已提交
682 683 684 685 686 687 688
        /**
         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改
         * @param {Object} newSeries
         * @param {Object} newComponent
         */
        function init(newOption, newComponent) {
            component = newComponent;
K
kener 已提交
689
            refresh(newOption);
K
kener 已提交
690 691 692 693 694
        }

        /**
         * 刷新
         */
K
kener 已提交
695 696 697 698 699
        function refresh(newOption) {
            if (newOption) {
                option = newOption;
                series = option.series;
            }
K
kener 已提交
700 701 702
            self.clear();
            _buildShape();
        }
K
kener 已提交
703 704 705 706 707
        
        function ontooltipHover(param, tipShape) {
            var seriesIndex = param.seriesIndex;
            var dataIndex = param.dataIndex;
            var seriesPL;
K
kener 已提交
708
            var singlePL;
K
kener 已提交
709 710 711 712 713 714 715 716
            var len = seriesIndex.length;
            while (len--) {
                seriesPL = finalPLMap[seriesIndex[len]];
                if (seriesPL) {
                    for (var i = 0, l = seriesPL.length; i < l; i++) {
                        singlePL = seriesPL[i];
                        for (var j = 0, k = singlePL.length; j < k; j++) {
                            if (dataIndex == singlePL[j][2]) {
K
kener 已提交
717 718 719 720 721 722
                                tipShape.push(_getSymbol(
                                    seriesIndex[len],   // seriesIndex
                                    singlePL[j][2],     // dataIndex
                                    singlePL[j][3],     // name
                                    singlePL[j][0],     // x
                                    singlePL[j][1],     // y
K
kener 已提交
723
                                    'horizontal'
K
kener 已提交
724
                                ));
K
kener 已提交
725 726 727 728 729 730
                            }
                        }
                    }
                }
            }
        }
K
kener 已提交
731

732 733 734 735 736 737 738 739 740 741 742 743 744
        /**
         * 动态数据增加动画 
         */
        function addDataAnimation(params) {
            var aniMap = {}; // seriesIndex索引参数
            for (var i = 0, l = params.length; i < l; i++) {
                aniMap[params[i][0]] = params[i];
            }
            var x;
            var dx;
            var y;
            var dy;
            var seriesIndex;
K
kener 已提交
745 746
            var pointList;
            var isHorizontal; // 是否横向布局, isHorizontal;
747 748 749 750 751
            for (var i = self.shapeList.length - 1; i >= 0; i--) {
                seriesIndex = self.shapeList[i]._seriesIndex;
                if (aniMap[seriesIndex] && !aniMap[seriesIndex][3]) {
                    // 有数据删除才有移动的动画
                    if (self.shapeList[i]._main) {
K
kener 已提交
752
                        pointList = self.shapeList[i].style.pointList;
753
                        // 主线动画
K
kener 已提交
754 755 756 757 758
                        dx = Math.abs(pointList[0][0] - pointList[1][0]);
                        dy = Math.abs(pointList[0][1] - pointList[1][1]);
                        isHorizontal = 
                            self.shapeList[i]._orient == 'horizontal';
                            
759 760
                        if (aniMap[seriesIndex][2]) {
                            // 队头加入删除末尾
K
kener 已提交
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
                            if (self.shapeList[i].shape == 'polygon') {
                                //区域图
                                var len = pointList.length;
                                self.shapeList[i].style.pointList[len - 3]
                                    = pointList[len - 2];
                                isHorizontal
                                ? (self.shapeList[i].style.pointList[len - 3][0]
                                       = pointList[len - 4][0]
                                  )
                                : (self.shapeList[i].style.pointList[len - 3][1]
                                       = pointList[len - 4][1]
                                  );
                                self.shapeList[i].style.pointList[len - 2]
                                    = pointList[len - 1];
                            }
776
                            self.shapeList[i].style.pointList.pop();
K
kener 已提交
777 778
                            
                            isHorizontal ? (x = dx, y = 0) : (x = 0, y = -dy);
779 780 781 782
                        }
                        else {
                            // 队尾加入删除头部
                            self.shapeList[i].style.pointList.shift();
K
kener 已提交
783 784 785 786 787 788 789 790 791 792 793 794
                            if (self.shapeList[i].shape == 'polygon') {
                                //区域图
                                var targetPoint = 
                                    self.shapeList[i].style.pointList.pop();
                                isHorizontal
                                ? (targetPoint[0] = pointList[0][0])
                                : (targetPoint[1] = pointList[0][1]);
                                self.shapeList[i].style.pointList.push(
                                    targetPoint
                                );
                            }
                            isHorizontal ? (x = -dx, y = 0) : (x = 0, y = dy);
795
                        }
K
kener 已提交
796 797 798 799 800 801 802 803 804
                        zr.modShape(
                            self.shapeList[i].id, 
                            {
                                style : {
                                    pointList: self.shapeList[i].style.pointList
                                }
                            },
                            true
                        );
805 806 807 808 809 810 811 812 813 814 815 816
                    }
                    else {
                        // 拐点动画
                        if (aniMap[seriesIndex][2] 
                            && self.shapeList[i]._dataIndex 
                                == series[seriesIndex].data.length - 1
                        ) {
                            // 队头加入删除末尾
                            zr.delShape(self.shapeList[i].id);
                            continue;
                        }
                        else if (!aniMap[seriesIndex][2] 
K
kener 已提交
817
                                 && self.shapeList[i]._dataIndex === 0
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
                        ) {
                            // 队尾加入删除头部
                            zr.delShape(self.shapeList[i].id);
                            continue;
                        }
                    }
                    zr.animate(self.shapeList[i].id, '')
                        .when(
                            500,
                            {position : [x, y]}
                        )
                        .start();
                }
            }
        }
        
K
kener 已提交
834 835 836 837
        /**
         * 动画设定
         */
        function animation() {
838 839
            var duration = self.query(option, 'animationDuration');
            var easing = self.query(option, 'animationEasing');
K
kener 已提交
840 841 842 843 844 845 846
            var x;
            var y;
            var serie;
            var dataIndex = 0;

            for (var i = 0, l = self.shapeList.length; i < l; i++) {
                if (self.shapeList[i]._main) {
K
kener 已提交
847
                    serie = series[self.shapeList[i]._seriesIndex];
K
kener 已提交
848 849 850 851
                    dataIndex += 1;
                    x = self.shapeList[i].style.pointList[0][0];
                    y = self.shapeList[i].style.pointList[0][1];
                    if (self.shapeList[i]._orient == 'horizontal') {
K
kener 已提交
852 853 854 855 856 857 858
                        zr.modShape(
                            self.shapeList[i].id, 
                            {
                                scale : [0, 1, x, y]
                            },
                            true
                        );
K
kener 已提交
859 860
                    }
                    else {
K
kener 已提交
861 862 863 864 865 866 867
                        zr.modShape(
                            self.shapeList[i].id, 
                            {
                                scale : [1, 0, x, y]
                            },
                            true
                        );
K
kener 已提交
868 869 870
                    }
                    zr.animate(self.shapeList[i].id, '')
                        .when(
871
                            (self.query(serie,'animationDuration')
K
kener 已提交
872 873
                            || duration)
                            + dataIndex * 100,
K
kener 已提交
874
                            {scale : [1, 1, x, y]}
K
kener 已提交
875
                        )
K
kener 已提交
876
                        .start(
877
                            self.query(serie, 'animationEasing') || easing
K
kener 已提交
878
                        );
K
kener 已提交
879 880
                }
            }
K
kener 已提交
881 882
            
            self.animationMark(duration, easing);
K
kener 已提交
883 884
        }

K
kener 已提交
885 886
        // 重载基类方法
        self.getMarkCoord = getMarkCoord;
K
kener 已提交
887
        self.animation = animation;
K
kener 已提交
888
        
K
kener 已提交
889 890
        self.init = init;
        self.refresh = refresh;
K
kener 已提交
891
        self.ontooltipHover = ontooltipHover;
892
        self.addDataAnimation = addDataAnimation;
K
kener 已提交
893 894 895 896

        init(option, component);
    }

897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
    function legendLineIcon(ctx, style) {
        var x = style.x;
        var y = style.y;
        var width = style.width;
        var height = style.height;
        
        var dy = height / 2;
        
        if (style.symbol.match('empty')) {
            ctx.fillStyle = '#fff';
        }
        style.brushType = 'both';
        
        var symbol = style.symbol.replace('empty', '').toLowerCase();
        if (symbol.match('star')) {
            dy = (symbol.replace('star','') - 0) || 5;
            y -= 1;
            symbol = 'star';
        } 
K
kener 已提交
916
        else if (symbol == 'rectangle' || symbol == 'arrow') {
917 918 919
            x += (width - height) / 2;
            width = height;
        }
K
kener 已提交
920 921 922 923 924 925 926
        
        var imageLocation = '';
        if (symbol.match('image')) {
            imageLocation = symbol.replace(
                    new RegExp('^image:\\/\\/'), ''
                );
            symbol = 'image';
K
kener 已提交
927 928
            x += Math.round((width - height) / 2) - 1;
            width = height = height + 2;
K
kener 已提交
929
        }
930 931 932
        symbol = require('zrender/shape').get('icon').get(symbol);
        
        if (symbol) {
933 934 935
            var x2 = style.x;
            var y2 = style.y;
            ctx.moveTo(x2, y2 + dy);
K
kener 已提交
936 937
            ctx.lineTo(x2 + 5, y2 + dy);
            ctx.moveTo(x2 + style.width - 5, y2 + dy);
938 939
            ctx.lineTo(x2 + style.width, y2 + dy);
            
940
            symbol(ctx, {
K
kener 已提交
941 942 943 944
                x : x + 4,
                y : y + 4,
                width : width - 8,
                height : height - 8,
K
kener 已提交
945 946
                n : dy,
                image : imageLocation
947
            });
948 949 950 951 952
            
        }
        else {
            ctx.moveTo(x, y + dy);
            ctx.lineTo(x + width, y + dy);
953 954
        }
    }
K
kener 已提交
955 956 957 958
    
    // 动态扩展zrender shape:halfSmoothPolygon
    require('../util/shape/halfSmoothPolygon');
    
959 960 961
    // 图表注册
    require('../chart').define('line', Line);
    
K
kener 已提交
962 963
    return Line;
});