/**
 * echarts图表基类
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */
module.exports = function (require) {
  // 图形依赖
  var ImageShape = require('zrender/shape/Image');

  var IconShape = require('../util/shape/Icon');

  var MarkLineShape = require('../util/shape/MarkLine');

  var SymbolShape = require('../util/shape/Symbol');

  var PolylineShape = require('zrender/shape/Polyline');

  var ShapeBundle = require('zrender/shape/ShapeBundle');

  var ecConfig = require('../config');

  var ecData = require('../util/ecData');

  var ecAnimation = require('../util/ecAnimation');

  var ecEffect = require('../util/ecEffect');

  var accMath = require('../util/accMath');

  var ComponentBase = require('../component/base');

  var EdgeBundling = require('../layout/EdgeBundling');

  var zrUtil = require('zrender/tool/util');

  var zrArea = require('zrender/tool/area'); // Some utility functions


  function isCoordAvailable(coord) {
    return coord.x != null && coord.y != null;
  }

  function Base(ecTheme, messageCenter, zr, option, myChart) {
    ComponentBase.call(this, ecTheme, messageCenter, zr, option, myChart);
    var self = this;
    this.selectedMap = {};
    this.lastShapeList = [];
    this.shapeHandler = {
      onclick: function () {
        self.isClick = true;
      },
      ondragover: function (param) {
        // 返回触发可计算特性的图形提示
        var calculableShape = param.target;
        calculableShape.highlightStyle = calculableShape.highlightStyle || {}; // 备份特出特性

        var highlightStyle = calculableShape.highlightStyle;
        var brushType = highlightStyle.brushTyep;
        var strokeColor = highlightStyle.strokeColor;
        var lineWidth = highlightStyle.lineWidth;
        highlightStyle.brushType = 'stroke';
        highlightStyle.strokeColor = self.ecTheme.calculableColor || ecConfig.calculableColor;
        highlightStyle.lineWidth = calculableShape.type === 'icon' ? 30 : 10;
        self.zr.addHoverShape(calculableShape);
        setTimeout(function () {
          // 复位
          if (highlightStyle) {
            highlightStyle.brushType = brushType;
            highlightStyle.strokeColor = strokeColor;
            highlightStyle.lineWidth = lineWidth;
          }
        }, 20);
      },
      ondrop: function (param) {
        // 排除一些非数据的拖拽进入
        if (ecData.get(param.dragged, 'data') != null) {
          self.isDrop = true;
        }
      },
      ondragend: function () {
        self.isDragend = true;
      }
    };
  }
  /**
   * 基类方法
   */


  Base.prototype = {
    /**
     * 图形拖拽特性 
     */
    setCalculable: function (shape) {
      shape.dragEnableTime = this.ecTheme.DRAG_ENABLE_TIME || ecConfig.DRAG_ENABLE_TIME;
      shape.ondragover = this.shapeHandler.ondragover;
      shape.ondragend = this.shapeHandler.ondragend;
      shape.ondrop = this.shapeHandler.ondrop;
      return shape;
    },

    /**
     * 数据项被拖拽进来
     */
    ondrop: function (param, status) {
      if (!this.isDrop || !param.target || status.dragIn) {
        // 没有在当前实例上发生拖拽行为或者已经被认领了则直接返回
        return;
      }

      var target = param.target; // 拖拽安放目标

      var dragged = param.dragged; // 当前被拖拽的图形对象

      var seriesIndex = ecData.get(target, 'seriesIndex');
      var dataIndex = ecData.get(target, 'dataIndex');
      var series = this.series;
      var data;
      var legend = this.component.legend;

      if (dataIndex === -1) {
        // 落到calculableCase上，数据被拖拽进某个饼图|雷达|漏斗，增加数据
        if (ecData.get(dragged, 'seriesIndex') == seriesIndex) {
          // 自己拖拽到自己
          status.dragOut = status.dragIn = status.needRefresh = true;
          this.isDrop = false;
          return;
        }

        data = {
          value: ecData.get(dragged, 'value'),
          name: ecData.get(dragged, 'name')
        }; // 修饼图数值不为负值

        if (this.type === ecConfig.CHART_TYPE_PIE && data.value < 0) {
          data.value = 0;
        }

        var hasFind = false;
        var sData = series[seriesIndex].data;

        for (var i = 0, l = sData.length; i < l; i++) {
          if (sData[i].name === data.name && sData[i].value === '-') {
            series[seriesIndex].data[i].value = data.value;
            hasFind = true;
          }
        }

        !hasFind && series[seriesIndex].data.push(data);
        legend && legend.add(data.name, dragged.style.color || dragged.style.strokeColor);
      } else {
        // 落到数据item上，数据被拖拽到某个数据项上，数据修改
        data = series[seriesIndex].data[dataIndex] || '-';

        if (data.value != null) {
          if (data.value != '-') {
            series[seriesIndex].data[dataIndex].value = accMath.accAdd(series[seriesIndex].data[dataIndex].value, ecData.get(dragged, 'value'));
          } else {
            series[seriesIndex].data[dataIndex].value = ecData.get(dragged, 'value');
          }

          if (this.type === ecConfig.CHART_TYPE_FUNNEL || this.type === ecConfig.CHART_TYPE_PIE) {
            legend && legend.getRelatedAmount(data.name) === 1 && this.component.legend.del(data.name);
            data.name += this.option.nameConnector + ecData.get(dragged, 'name');
            legend && legend.add(data.name, dragged.style.color || dragged.style.strokeColor);
          }
        } else {
          if (data != '-') {
            series[seriesIndex].data[dataIndex] = accMath.accAdd(series[seriesIndex].data[dataIndex], ecData.get(dragged, 'value'));
          } else {
            series[seriesIndex].data[dataIndex] = ecData.get(dragged, 'value');
          }
        }
      } // 别status = {}赋值啊！！


      status.dragIn = status.dragIn || true; // 处理完拖拽事件后复位

      this.isDrop = false;
      var self = this;
      setTimeout(function () {
        self.zr.trigger('mousemove', param.event);
      }, 300);
      return;
    },

    /**
     * 数据项被拖拽出去
     */
    ondragend: function (param, status) {
      if (!this.isDragend || !param.target || status.dragOut) {
        // 没有在当前实例上发生拖拽行为或者已经被认领了则直接返回
        return;
      }

      var target = param.target; // 被拖拽图形元素

      var seriesIndex = ecData.get(target, 'seriesIndex');
      var dataIndex = ecData.get(target, 'dataIndex');
      var series = this.series; // 删除被拖拽走的数据

      if (series[seriesIndex].data[dataIndex].value != null) {
        series[seriesIndex].data[dataIndex].value = '-'; // 清理可能有且唯一的legend data

        var name = series[seriesIndex].data[dataIndex].name;
        var legend = this.component.legend;

        if (legend && legend.getRelatedAmount(name) === 0) {
          legend.del(name);
        }
      } else {
        series[seriesIndex].data[dataIndex] = '-';
      } // 别status = {}赋值啊！！


      status.dragOut = true;
      status.needRefresh = true; // 处理完拖拽事件后复位

      this.isDragend = false;
      return;
    },

    /**
     * 图例选择
     */
    onlegendSelected: function (param, status) {
      var legendSelected = param.selected;

      for (var itemName in this.selectedMap) {
        if (this.selectedMap[itemName] != legendSelected[itemName]) {
          // 有一项不一致都需要重绘
          status.needRefresh = true;
        }

        this.selectedMap[itemName] = legendSelected[itemName];
      }

      return;
    },

    /**
     * 折线图、柱形图公用方法
     */
    _buildPosition: function () {
      this._symbol = this.option.symbolList;
      this._sIndex2ShapeMap = {}; // series拐点图形类型，seriesIndex索引到shape type

      this._sIndex2ColorMap = {}; // series默认颜色索引，seriesIndex索引到color

      this.selectedMap = {};
      this.xMarkMap = {};
      var series = this.series; // 水平垂直双向series索引 ，position索引到seriesIndex

      var _position2sIndexMap = {
        top: [],
        bottom: [],
        left: [],
        right: [],
        other: []
      };
      var xAxisIndex;
      var yAxisIndex;
      var xAxis;
      var yAxis;

      for (var i = 0, l = series.length; i < l; i++) {
        if (series[i].type === this.type) {
          series[i] = this.reformOption(series[i]);
          this.legendHoverLink = series[i].legendHoverLink || this.legendHoverLink;
          xAxisIndex = series[i].xAxisIndex;
          yAxisIndex = series[i].yAxisIndex;
          xAxis = this.component.xAxis.getAxis(xAxisIndex);
          yAxis = this.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);
          } else {
            _position2sIndexMap.other.push(i);
          }
        }
      } // console.log(_position2sIndexMap);


      for (var position in _position2sIndexMap) {
        if (_position2sIndexMap[position].length > 0) {
          this._buildSinglePosition(position, _position2sIndexMap[position]);
        }
      }

      this.addShapeList();
    },

    /**
     * 构建单个方向上的折线图、柱形图公用方法
     *
     * @param {number} seriesIndex 系列索引
     */
    _buildSinglePosition: function (position, seriesArray) {
      var mapData = this._mapData(seriesArray);

      var locationMap = mapData.locationMap;
      var maxDataLength = mapData.maxDataLength;

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

      switch (position) {
        case 'bottom':
        case 'top':
          this._buildHorizontal(seriesArray, maxDataLength, locationMap, this.xMarkMap);

          break;

        case 'left':
        case 'right':
          this._buildVertical(seriesArray, maxDataLength, locationMap, this.xMarkMap);

          break;

        case 'other':
          this._buildOther(seriesArray, maxDataLength, locationMap, this.xMarkMap);

          break;
      }

      for (var i = 0, l = seriesArray.length; i < l; i++) {
        this.buildMark(seriesArray[i]);
      }
    },

    /**
     * 数据整形，折线图、柱形图公用方法
     * 数组位置映射到系列索引
     */
    _mapData: function (seriesArray) {
      var series = this.series;
      var serie; // 临时映射变量

      var dataIndex = 0; // 堆积数据所在位置映射

      var stackMap = {}; // 堆积数据位置映射，堆积组在二维中的第几项

      var magicStackKey = '__kener__stack__'; // 堆积命名，非堆积数据安单一堆积处理

      var stackKey; // 临时映射变量

      var serieName; // 临时映射变量

      var legend = this.component.legend;
      var locationMap = []; // 需要返回的东西：数组位置映射到系列索引

      var maxDataLength = 0; // 需要返回的东西：最大数据长度

      var iconShape; // 计算需要显示的个数和分配位置并记在下面这个结构里

      for (var i = 0, l = seriesArray.length; i < l; i++) {
        serie = series[seriesArray[i]];
        serieName = serie.name;
        this._sIndex2ShapeMap[seriesArray[i]] = this._sIndex2ShapeMap[seriesArray[i]] || this.query(serie, 'symbol') || this._symbol[i % this._symbol.length];

        if (legend) {
          this.selectedMap[serieName] = legend.isSelected(serieName);
          this._sIndex2ColorMap[seriesArray[i]] = legend.getColor(serieName);
          iconShape = legend.getItemShape(serieName);

          if (iconShape) {
            // 回调legend，换一个更形象的icon
            var style = iconShape.style;

            if (this.type == ecConfig.CHART_TYPE_LINE) {
              style.iconType = 'legendLineIcon';
              style.symbol = this._sIndex2ShapeMap[seriesArray[i]];
            } else if (serie.itemStyle.normal.barBorderWidth > 0) {
              var highlightStyle = iconShape.highlightStyle;
              style.brushType = 'both';
              style.x += 1;
              style.y += 1;
              style.width -= 2;
              style.height -= 2;
              style.strokeColor = highlightStyle.strokeColor = serie.itemStyle.normal.barBorderColor;
              highlightStyle.lineWidth = 3;
            }

            legend.setItemShape(serieName, iconShape);
          }
        } else {
          this.selectedMap[serieName] = true;
          this._sIndex2ColorMap[seriesArray[i]] = this.zr.getColor(seriesArray[i]);
        }

        if (this.selectedMap[serieName]) {
          stackKey = serie.stack || magicStackKey + seriesArray[i];

          if (stackMap[stackKey] == null) {
            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
      };
    },
    _calculMarkMapXY: function (xMarkMap, locationMap, xy) {
      var series = this.series;

      for (var j = 0, k = locationMap.length; j < k; j++) {
        for (var m = 0, n = locationMap[j].length; m < n; m++) {
          var seriesIndex = locationMap[j][m];
          var valueIndex = xy == 'xy' ? 0 : '';
          var grid = this.component.grid;
          var tarMark = xMarkMap[seriesIndex];

          if (xy.indexOf('x') != '-1') {
            if (tarMark['counter' + valueIndex] > 0) {
              tarMark['average' + valueIndex] = tarMark['sum' + valueIndex] / tarMark['counter' + valueIndex];
            }

            var x = this.component.xAxis.getAxis(series[seriesIndex].xAxisIndex || 0).getCoord(tarMark['average' + valueIndex]);
            tarMark['averageLine' + valueIndex] = [[x, grid.getYend()], [x, grid.getY()]];
            tarMark['minLine' + valueIndex] = [[tarMark['minX' + valueIndex], grid.getYend()], [tarMark['minX' + valueIndex], grid.getY()]];
            tarMark['maxLine' + valueIndex] = [[tarMark['maxX' + valueIndex], grid.getYend()], [tarMark['maxX' + valueIndex], grid.getY()]];
            tarMark.isHorizontal = false;
          }

          valueIndex = xy == 'xy' ? 1 : '';

          if (xy.indexOf('y') != '-1') {
            if (tarMark['counter' + valueIndex] > 0) {
              tarMark['average' + valueIndex] = tarMark['sum' + valueIndex] / tarMark['counter' + valueIndex];
            }

            var y = this.component.yAxis.getAxis(series[seriesIndex].yAxisIndex || 0).getCoord(tarMark['average' + valueIndex]);
            tarMark['averageLine' + valueIndex] = [[grid.getX(), y], [grid.getXend(), y]];
            tarMark['minLine' + valueIndex] = [[grid.getX(), tarMark['minY' + valueIndex]], [grid.getXend(), tarMark['minY' + valueIndex]]];
            tarMark['maxLine' + valueIndex] = [[grid.getX(), tarMark['maxY' + valueIndex]], [grid.getXend(), tarMark['maxY' + valueIndex]]];
            tarMark.isHorizontal = true;
          }
        }
      }
    },

    /**
     * 添加文本 
     */
    addLabel: function (tarShape, serie, data, name, orient) {
      // 多级控制
      var queryTarget = [data, serie];
      var nLabel = this.deepMerge(queryTarget, 'itemStyle.normal.label');
      var eLabel = this.deepMerge(queryTarget, 'itemStyle.emphasis.label');
      var nTextStyle = nLabel.textStyle || {};
      var eTextStyle = eLabel.textStyle || {};

      if (nLabel.show) {
        var style = tarShape.style;
        style.text = this._getLabelText(serie, data, name, 'normal');
        style.textPosition = nLabel.position == null ? orient === 'horizontal' ? 'right' : 'top' : nLabel.position;
        style.textColor = nTextStyle.color;
        style.textFont = this.getFont(nTextStyle);
        style.textAlign = nTextStyle.align;
        style.textBaseline = nTextStyle.baseline;
      }

      if (eLabel.show) {
        var highlightStyle = tarShape.highlightStyle;
        highlightStyle.text = this._getLabelText(serie, data, name, 'emphasis');
        highlightStyle.textPosition = nLabel.show ? tarShape.style.textPosition : eLabel.position == null ? orient === 'horizontal' ? 'right' : 'top' : eLabel.position;
        highlightStyle.textColor = eTextStyle.color;
        highlightStyle.textFont = this.getFont(eTextStyle);
        highlightStyle.textAlign = eTextStyle.align;
        highlightStyle.textBaseline = eTextStyle.baseline;
      }

      return tarShape;
    },

    /**
     * 根据lable.format计算label text
     */
    _getLabelText: function (serie, data, name, status) {
      var formatter = this.deepQuery([data, serie], 'itemStyle.' + status + '.label.formatter');

      if (!formatter && status === 'emphasis') {
        // emphasis时需要看看normal下是否有formatter
        formatter = this.deepQuery([data, serie], 'itemStyle.normal.label.formatter');
      }

      var value = this.getDataFromOption(data, '-');

      if (formatter) {
        if (typeof formatter === 'function') {
          return formatter.call(this.myChart, {
            seriesName: serie.name,
            series: serie,
            name: name,
            value: value,
            data: data,
            status: status
          });
        } else if (typeof formatter === 'string') {
          formatter = formatter.replace('{a}', '{a0}').replace('{b}', '{b0}').replace('{c}', '{c0}').replace('{a0}', serie.name).replace('{b0}', name).replace('{c0}', this.numAddCommas(value));
          return formatter;
        }
      } else {
        if (value instanceof Array) {
          return value[2] != null ? this.numAddCommas(value[2]) : value[0] + ' , ' + value[1];
        } else {
          return this.numAddCommas(value);
        }
      }
    },

    /**
     * 标线标注 
     */
    buildMark: function (seriesIndex) {
      var serie = this.series[seriesIndex];

      if (this.selectedMap[serie.name]) {
        serie.markLine && this._buildMarkLine(seriesIndex);
        serie.markPoint && this._buildMarkPoint(seriesIndex);
      }
    },

    /**
     * 标注逻辑
     */
    _buildMarkPoint: function (seriesIndex) {
      var attachStyle = (this.markAttachStyle || {})[seriesIndex];
      var serie = this.series[seriesIndex];
      var mpData;
      var pos;
      var markPoint = zrUtil.clone(serie.markPoint);

      for (var i = 0, l = markPoint.data.length; i < l; i++) {
        mpData = markPoint.data[i];
        pos = this.getMarkCoord(seriesIndex, mpData);
        mpData.x = mpData.x != null ? mpData.x : pos[0];
        mpData.y = mpData.y != null ? mpData.y : pos[1];

        if (mpData.type && (mpData.type === 'max' || mpData.type === 'min')) {
          // 特殊值内置支持
          mpData.value = pos[3];
          mpData.name = mpData.name || mpData.type;
          mpData.symbolSize = mpData.symbolSize || zrArea.getTextWidth(pos[3], this.getFont()) / 2 + 5;
        }
      }

      var shapeList = this._markPoint(seriesIndex, markPoint);

      for (var i = 0, l = shapeList.length; i < l; i++) {
        var tarShape = shapeList[i];
        tarShape.zlevel = serie.zlevel;
        tarShape.z = serie.z + 1;

        for (var key in attachStyle) {
          tarShape[key] = zrUtil.clone(attachStyle[key]);
        }

        this.shapeList.push(tarShape);
      } // 个别特殊图表需要自己addShape


      if (this.type === ecConfig.CHART_TYPE_FORCE || this.type === ecConfig.CHART_TYPE_CHORD) {
        for (var i = 0, l = shapeList.length; i < l; i++) {
          this.zr.addShape(shapeList[i]);
        }
      }
    },

    /**
     * 标线逻辑
     */
    _buildMarkLine: function (seriesIndex) {
      var attachStyle = (this.markAttachStyle || {})[seriesIndex];
      var serie = this.series[seriesIndex];
      var pos;
      var markLine = zrUtil.clone(serie.markLine);

      for (var i = 0, l = markLine.data.length; i < l; i++) {
        var mlData = markLine.data[i];

        if (mlData.type && (mlData.type === 'max' || mlData.type === 'min' || mlData.type === 'average')) {
          // 特殊值内置支持
          pos = this.getMarkCoord(seriesIndex, mlData);
          markLine.data[i] = [zrUtil.clone(mlData), {}];
          markLine.data[i][0].name = mlData.name || mlData.type;
          markLine.data[i][0].value = mlData.type !== 'average' ? pos[3] : +pos[3].toFixed(markLine.precision != null ? markLine.precision : this.deepQuery([this.ecTheme, ecConfig], 'markLine.precision'));
          pos = pos[2];
          mlData = [{}, {}];
        } else {
          pos = [this.getMarkCoord(seriesIndex, mlData[0]), this.getMarkCoord(seriesIndex, mlData[1])];
        }

        if (pos == null || pos[0] == null || pos[1] == null) {
          // 不在显示区域内
          continue;
        }

        markLine.data[i][0].x = mlData[0].x != null ? mlData[0].x : pos[0][0];
        markLine.data[i][0].y = mlData[0].y != null ? mlData[0].y : pos[0][1];
        markLine.data[i][1].x = mlData[1].x != null ? mlData[1].x : pos[1][0];
        markLine.data[i][1].y = mlData[1].y != null ? mlData[1].y : pos[1][1];
      }

      var shapeList = this._markLine(seriesIndex, markLine);

      var isLarge = markLine.large;

      if (isLarge) {
        var shapeBundle = new ShapeBundle({
          style: {
            shapeList: shapeList
          }
        });
        var firstShape = shapeList[0];

        if (firstShape) {
          zrUtil.merge(shapeBundle.style, firstShape.style);
          zrUtil.merge(shapeBundle.highlightStyle = {}, firstShape.highlightStyle);
          shapeBundle.style.brushType = 'stroke';
          shapeBundle.zlevel = serie.zlevel;
          shapeBundle.z = serie.z + 1;
          shapeBundle.hoverable = false;

          for (var key in attachStyle) {
            shapeBundle[key] = zrUtil.clone(attachStyle[key]);
          }
        }

        this.shapeList.push(shapeBundle);
        this.zr.addShape(shapeBundle);
        shapeBundle._mark = 'largeLine';
        var effect = markLine.effect;

        if (effect.show) {
          shapeBundle.effect = effect;
        }
      } else {
        for (var i = 0, l = shapeList.length; i < l; i++) {
          var tarShape = shapeList[i];
          tarShape.zlevel = serie.zlevel;
          tarShape.z = serie.z + 1;

          for (var key in attachStyle) {
            tarShape[key] = zrUtil.clone(attachStyle[key]);
          }

          this.shapeList.push(tarShape);
        } // 个别特殊图表需要自己addShape


        if (this.type === ecConfig.CHART_TYPE_FORCE || this.type === ecConfig.CHART_TYPE_CHORD) {
          for (var i = 0, l = shapeList.length; i < l; i++) {
            this.zr.addShape(shapeList[i]);
          }
        }
      }
    },

    /**
     * 标注多级控制构造
     */
    _markPoint: function (seriesIndex, mpOption) {
      var serie = this.series[seriesIndex];
      var component = this.component;
      zrUtil.merge(zrUtil.merge(mpOption, zrUtil.clone(this.ecTheme.markPoint || {})), zrUtil.clone(ecConfig.markPoint));
      mpOption.name = serie.name;
      var pList = [];
      var data = mpOption.data;
      var itemShape;
      var dataRange = component.dataRange;
      var legend = component.legend;
      var color;
      var value;
      var queryTarget;
      var nColor;
      var eColor;
      var effect;
      var zrWidth = this.zr.getWidth();
      var zrHeight = this.zr.getHeight();

      if (!mpOption.large) {
        for (var i = 0, l = data.length; i < l; i++) {
          if (data[i].x == null || data[i].y == null) {
            continue;
          }

          value = data[i].value != null ? data[i].value : ''; // 图例

          if (legend) {
            color = legend.getColor(serie.name);
          } // 值域


          if (dataRange) {
            color = isNaN(value) ? color : dataRange.getColor(value);
            queryTarget = [data[i], mpOption];
            nColor = this.deepQuery(queryTarget, 'itemStyle.normal.color') || color;
            eColor = this.deepQuery(queryTarget, 'itemStyle.emphasis.color') || nColor; // 有值域，并且值域返回null且用户没有自己定义颜色，则隐藏这个mark

            if (nColor == null && eColor == null) {
              continue;
            }
          }

          color = color == null ? this.zr.getColor(seriesIndex) : color; // 标准化一些参数

          data[i].tooltip = data[i].tooltip || mpOption.tooltip || {
            trigger: 'item'
          }; // tooltip.trigger指定为item

          data[i].name = data[i].name != null ? data[i].name : '';
          data[i].value = value; // 复用getSymbolShape

          itemShape = this.getSymbolShape(mpOption, seriesIndex, // 系列 
          data[i], i, data[i].name, // 数据
          this.parsePercent(data[i].x, zrWidth), // 坐标
          this.parsePercent(data[i].y, zrHeight), // 坐标
          'pin', color, // 默认symbol和color
          'rgba(0,0,0,0)', 'horizontal' // 走向，用于默认文字定位
          );
          itemShape._mark = 'point';
          effect = this.deepMerge([data[i], mpOption], 'effect');

          if (effect.show) {
            itemShape.effect = effect;
          }

          if (serie.type === ecConfig.CHART_TYPE_MAP) {
            itemShape._geo = this.getMarkGeo(data[i]);
          } // 重新pack一下数据


          ecData.pack(itemShape, serie, seriesIndex, data[i], i, data[i].name, value);
          pList.push(itemShape);
        }
      } else {
        // 大规模MarkPoint
        itemShape = this.getLargeMarkPointShape(seriesIndex, mpOption);
        itemShape._mark = 'largePoint';
        itemShape && pList.push(itemShape);
      }

      return pList;
    },

    /**
     * 标线多级控制构造
     */
    _markLine: function () {
      function normalizeOptionValue(mlOption, key) {
        mlOption[key] = mlOption[key] instanceof Array ? mlOption[key].length > 1 ? mlOption[key] : [mlOption[key][0], mlOption[key][0]] : [mlOption[key], mlOption[key]];
      }

      return function (seriesIndex, mlOption) {
        var serie = this.series[seriesIndex];
        var component = this.component;
        var dataRange = component.dataRange;
        var legend = component.legend;
        zrUtil.merge(zrUtil.merge(mlOption, zrUtil.clone(this.ecTheme.markLine || {})), zrUtil.clone(ecConfig.markLine));
        var defaultColor = legend ? legend.getColor(serie.name) : this.zr.getColor(seriesIndex); // 标准化一些同时支持Array和String的参数

        normalizeOptionValue(mlOption, 'symbol');
        normalizeOptionValue(mlOption, 'symbolSize');
        normalizeOptionValue(mlOption, 'symbolRotate'); // Normalize and filter data

        var data = mlOption.data;
        var edges = [];
        var zrWidth = this.zr.getWidth();
        var zrHeight = this.zr.getHeight();

        for (var i = 0; i < data.length; i++) {
          var mlData = data[i];

          if (isCoordAvailable(mlData[0]) && isCoordAvailable(mlData[1])) {
            // 组装一个mergeData
            var mergeData = this.deepMerge(mlData);
            var queryTarget = [mergeData, mlOption];
            var color = defaultColor;
            var value = mergeData.value != null ? mergeData.value : ''; // 值域

            if (dataRange) {
              color = isNaN(value) ? color : dataRange.getColor(value);
              var nColor = this.deepQuery(queryTarget, 'itemStyle.normal.color') || color;
              var eColor = this.deepQuery(queryTarget, 'itemStyle.emphasis.color') || nColor; // 有值域，并且值域返回null且用户没有自己定义颜色，则隐藏这个mark

              if (nColor == null && eColor == null) {
                continue;
              }
            } // 标准化一些参数


            mlData[0].tooltip = mergeData.tooltip || mlOption.tooltip || {
              trigger: 'item'
            }; // tooltip.trigger指定为item

            mlData[0].name = mlData[0].name || '';
            mlData[1].name = mlData[1].name || '';
            mlData[0].value = value;
            edges.push({
              points: [[this.parsePercent(mlData[0].x, zrWidth), this.parsePercent(mlData[0].y, zrHeight)], [this.parsePercent(mlData[1].x, zrWidth), this.parsePercent(mlData[1].y, zrHeight)]],
              rawData: mlData,
              color: color
            });
          }
        }

        var enableBundling = this.query(mlOption, 'bundling.enable');

        if (enableBundling) {
          var edgeBundling = new EdgeBundling();
          edgeBundling.maxTurningAngle = this.query(mlOption, 'bundling.maxTurningAngle') / 180 * Math.PI;
          edges = edgeBundling.run(edges);
        }

        mlOption.name = serie.name;
        var shapeList = [];

        for (var i = 0, l = edges.length; i < l; i++) {
          var edge = edges[i];
          var rawEdge = edge.rawEdge || edge;
          var mlData = rawEdge.rawData;
          var value = mlData.value != null ? mlData.value : '';
          var itemShape = this.getMarkLineShape(mlOption, seriesIndex, mlData, i, edge.points, enableBundling, rawEdge.color);
          itemShape._mark = 'line';
          var effect = this.deepMerge([mlData[0], mlData[1], mlOption], 'effect');

          if (effect.show) {
            itemShape.effect = effect;
            itemShape.effect.large = mlOption.large;
          }

          if (serie.type === ecConfig.CHART_TYPE_MAP) {
            itemShape._geo = [this.getMarkGeo(mlData[0]), this.getMarkGeo(mlData[1])];
          } // 重新pack一下数据


          ecData.pack(itemShape, serie, seriesIndex, mlData[0], i, mlData[0].name // 不要帮我代码规范
          + (mlData[1].name !== '' ? ' > ' + mlData[1].name : ''), value);
          shapeList.push(itemShape);
        }

        return shapeList;
      };
    }(),
    getMarkCoord: function () {
      // 无转换位置
      return [0, 0];
    },

    /**
     * symbol构造器 
     */
    getSymbolShape: function (serie, seriesIndex, // 系列 
    data, dataIndex, name, // 数据
    x, y, // 坐标
    symbol, color, // 默认symbol和color，来自legend或dataRange全局分配
    emptyColor, // 折线的emptySymbol用白色填充
    orient // 走向，用于默认文字定位
    ) {
      var queryTarget = [data, serie];
      var value = this.getDataFromOption(data, '-');
      symbol = this.deepQuery(queryTarget, 'symbol') || symbol;
      var symbolSize = this.deepQuery(queryTarget, 'symbolSize');
      symbolSize = typeof symbolSize === 'function' ? symbolSize(value) : symbolSize;

      if (typeof symbolSize === 'number') {
        symbolSize = [symbolSize, symbolSize];
      }

      var symbolRotate = this.deepQuery(queryTarget, 'symbolRotate');
      var normal = this.deepMerge(queryTarget, 'itemStyle.normal');
      var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis');
      var nBorderWidth = normal.borderWidth != null ? normal.borderWidth : normal.lineStyle && normal.lineStyle.width;

      if (nBorderWidth == null) {
        nBorderWidth = symbol.match('empty') ? 2 : 0;
      }

      var eBorderWidth = emphasis.borderWidth != null ? emphasis.borderWidth : emphasis.lineStyle && emphasis.lineStyle.width;

      if (eBorderWidth == null) {
        eBorderWidth = nBorderWidth + 2;
      }

      var nColor = this.getItemStyleColor(normal.color, seriesIndex, dataIndex, data);
      var eColor = this.getItemStyleColor(emphasis.color, seriesIndex, dataIndex, data);
      var width = symbolSize[0];
      var height = symbolSize[1];
      var itemShape = new IconShape({
        style: {
          iconType: symbol.replace('empty', '').toLowerCase(),
          x: x - width,
          y: y - height,
          width: width * 2,
          height: height * 2,
          brushType: 'both',
          color: symbol.match('empty') ? emptyColor : nColor || color,
          strokeColor: normal.borderColor || nColor || color,
          lineWidth: nBorderWidth
        },
        highlightStyle: {
          color: symbol.match('empty') ? emptyColor : eColor || nColor || color,
          strokeColor: emphasis.borderColor || normal.borderColor || eColor || nColor || color,
          lineWidth: eBorderWidth
        },
        clickable: this.deepQuery(queryTarget, 'clickable')
      });

      if (symbol.match('image')) {
        itemShape.style.image = symbol.replace(new RegExp('^image:\\/\\/'), '');
        itemShape = new ImageShape({
          style: itemShape.style,
          highlightStyle: itemShape.highlightStyle,
          clickable: this.deepQuery(queryTarget, 'clickable')
        });
      }

      if (symbolRotate != null) {
        itemShape.rotation = [symbolRotate * Math.PI / 180, x, y];
      }

      if (symbol.match('star')) {
        itemShape.style.iconType = 'star';
        itemShape.style.n = symbol.replace('empty', '').replace('star', '') - 0 || 5;
      }

      if (symbol === 'none') {
        itemShape.invisible = true;
        itemShape.hoverable = false;
      }
      /*
      if (this.deepQuery([data, serie, option], 'calculable')) {
          this.setCalculable(itemShape);
          itemShape.draggable = true;
      }
      */


      itemShape = this.addLabel(itemShape, serie, data, name, orient);

      if (symbol.match('empty')) {
        if (itemShape.style.textColor == null) {
          itemShape.style.textColor = itemShape.style.strokeColor;
        }

        if (itemShape.highlightStyle.textColor == null) {
          itemShape.highlightStyle.textColor = itemShape.highlightStyle.strokeColor;
        }
      }

      ecData.pack(itemShape, serie, seriesIndex, data, dataIndex, name);
      itemShape._x = x;
      itemShape._y = y;
      itemShape._dataIndex = dataIndex;
      itemShape._seriesIndex = seriesIndex;
      return itemShape;
    },

    /**
     * 标线构造器 
     */
    getMarkLineShape: function (mlOption, // 系列 
    seriesIndex, // 系列索引
    data, // 数据
    dataIndex, // 数据索引
    points, // 坐标点
    bundling, // 是否边捆绑过
    color // 默认color，来自legend或dataRange全局分配
    ) {
      var value0 = data[0].value != null ? data[0].value : '-';
      var value1 = data[1].value != null ? data[1].value : '-';
      var symbol = [data[0].symbol || mlOption.symbol[0], data[1].symbol || mlOption.symbol[1]];
      var symbolSize = [data[0].symbolSize || mlOption.symbolSize[0], data[1].symbolSize || mlOption.symbolSize[1]];
      symbolSize[0] = typeof symbolSize[0] === 'function' ? symbolSize[0](value0) : symbolSize[0];
      symbolSize[1] = typeof symbolSize[1] === 'function' ? symbolSize[1](value1) : symbolSize[1];
      var symbolRotate = [this.query(data[0], 'symbolRotate') || mlOption.symbolRotate[0], this.query(data[1], 'symbolRotate') || mlOption.symbolRotate[1]]; //console.log(symbol, symbolSize, symbolRotate);

      var queryTarget = [data[0], data[1], mlOption];
      var normal = this.deepMerge(queryTarget, 'itemStyle.normal');
      normal.color = this.getItemStyleColor(normal.color, seriesIndex, dataIndex, data);
      var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis');
      emphasis.color = this.getItemStyleColor(emphasis.color, seriesIndex, dataIndex, data);
      var nlineStyle = normal.lineStyle;
      var elineStyle = emphasis.lineStyle;
      var nBorderWidth = nlineStyle.width;

      if (nBorderWidth == null) {
        nBorderWidth = normal.borderWidth;
      }

      var eBorderWidth = elineStyle.width;

      if (eBorderWidth == null) {
        eBorderWidth = emphasis.borderWidth != null ? emphasis.borderWidth : nBorderWidth + 2;
      }

      var smoothness = this.deepQuery(queryTarget, 'smoothness');

      if (!this.deepQuery(queryTarget, 'smooth')) {
        smoothness = 0;
      }

      var ShapeCtor = bundling ? PolylineShape : MarkLineShape;
      var itemShape = new ShapeCtor({
        style: {
          symbol: symbol,
          symbolSize: symbolSize,
          symbolRotate: symbolRotate,
          // data: [data[0].name,data[1].name],
          brushType: 'both',
          lineType: nlineStyle.type,
          shadowColor: nlineStyle.shadowColor || nlineStyle.color || normal.borderColor || normal.color || color,
          shadowBlur: nlineStyle.shadowBlur,
          shadowOffsetX: nlineStyle.shadowOffsetX,
          shadowOffsetY: nlineStyle.shadowOffsetY,
          color: normal.color || color,
          strokeColor: nlineStyle.color || normal.borderColor || normal.color || color,
          lineWidth: nBorderWidth,
          symbolBorderColor: normal.borderColor || normal.color || color,
          symbolBorder: normal.borderWidth
        },
        highlightStyle: {
          shadowColor: elineStyle.shadowColor,
          shadowBlur: elineStyle.shadowBlur,
          shadowOffsetX: elineStyle.shadowOffsetX,
          shadowOffsetY: elineStyle.shadowOffsetY,
          color: emphasis.color || normal.color || color,
          strokeColor: elineStyle.color || nlineStyle.color || emphasis.borderColor || normal.borderColor || emphasis.color || normal.color || color,
          lineWidth: eBorderWidth,
          symbolBorderColor: emphasis.borderColor || normal.borderColor || emphasis.color || normal.color || color,
          symbolBorder: emphasis.borderWidth == null ? normal.borderWidth + 2 : emphasis.borderWidth
        },
        clickable: this.deepQuery(queryTarget, 'clickable')
      });
      var shapeStyle = itemShape.style;

      if (bundling) {
        shapeStyle.pointList = points;
        shapeStyle.smooth = smoothness;
      } else {
        shapeStyle.xStart = points[0][0];
        shapeStyle.yStart = points[0][1];
        shapeStyle.xEnd = points[1][0];
        shapeStyle.yEnd = points[1][1];
        shapeStyle.curveness = smoothness;
        itemShape.updatePoints(itemShape.style);
      }

      itemShape = this.addLabel(itemShape, mlOption, data[0], data[0].name + ' : ' + data[1].name);
      return itemShape;
    },

    /**
     * 大规模标注构造器 
     */
    getLargeMarkPointShape: function (seriesIndex, mpOption) {
      var serie = this.series[seriesIndex];
      var component = this.component;
      var data = mpOption.data;
      var itemShape;
      var dataRange = component.dataRange;
      var legend = component.legend;
      var color;
      var value;
      var queryTarget = [data[0], mpOption];
      var nColor;
      var eColor;
      var effect; // 图例

      if (legend) {
        color = legend.getColor(serie.name);
      } // 值域


      if (dataRange) {
        value = data[0].value != null ? data[0].value : '';
        color = isNaN(value) ? color : dataRange.getColor(value);
        nColor = this.deepQuery(queryTarget, 'itemStyle.normal.color') || color;
        eColor = this.deepQuery(queryTarget, 'itemStyle.emphasis.color') || nColor; // 有值域，并且值域返回null且用户没有自己定义颜色，则隐藏这个mark

        if (nColor == null && eColor == null) {
          return;
        }
      }

      color = this.deepMerge(queryTarget, 'itemStyle.normal').color || color;
      var symbol = this.deepQuery(queryTarget, 'symbol') || 'circle';
      symbol = symbol.replace('empty', '').replace(/\d/g, '');
      effect = this.deepMerge([data[0], mpOption], 'effect');
      var devicePixelRatio = window.devicePixelRatio || 1; //console.log(data)

      itemShape = new SymbolShape({
        style: {
          pointList: data,
          color: color,
          strokeColor: color,
          shadowColor: effect.shadowColor || color,
          shadowBlur: (effect.shadowBlur != null ? effect.shadowBlur : 8) * devicePixelRatio,
          size: this.deepQuery(queryTarget, 'symbolSize'),
          iconType: symbol,
          brushType: 'fill',
          lineWidth: 1
        },
        draggable: false,
        hoverable: false
      });

      if (effect.show) {
        itemShape.effect = effect;
      }

      return itemShape;
    },
    backupShapeList: function () {
      if (this.shapeList && this.shapeList.length > 0) {
        this.lastShapeList = this.shapeList;
        this.shapeList = [];
      } else {
        this.lastShapeList = [];
      }
    },
    addShapeList: function () {
      var maxLenth = this.option.animationThreshold / (this.canvasSupported ? 2 : 4);
      var lastShapeList = this.lastShapeList;
      var shapeList = this.shapeList;
      var isUpdate = lastShapeList.length > 0;
      var duration = isUpdate ? this.query(this.option, 'animationDurationUpdate') : this.query(this.option, 'animationDuration');
      var easing = this.query(this.option, 'animationEasing');
      var delay;
      var key;
      var oldMap = {};
      var newMap = {};

      if (this.option.animation && !this.option.renderAsImage && shapeList.length < maxLenth && !this.motionlessOnce) {
        // 通过已有的shape做动画过渡
        for (var i = 0, l = lastShapeList.length; i < l; i++) {
          key = this._getAnimationKey(lastShapeList[i]);

          if (key.match('undefined')) {
            this.zr.delShape(lastShapeList[i].id); // 非关键元素直接删除
          } else {
            key += lastShapeList[i].type; // https://github.com/ecomfe/echarts/issues/1219#issuecomment-71987602
            // 响应中断可能产生的重复元素

            if (oldMap[key]) {
              this.zr.delShape(lastShapeList[i].id);
            } else {
              oldMap[key] = lastShapeList[i];
            }
          }
        }

        for (var i = 0, l = shapeList.length; i < l; i++) {
          key = this._getAnimationKey(shapeList[i]);

          if (key.match('undefined')) {
            this.zr.addShape(shapeList[i]); // 非关键元素直接添加
          } else {
            key += shapeList[i].type;
            newMap[key] = shapeList[i];
          }
        }

        for (key in oldMap) {
          if (!newMap[key]) {
            // 新的没有 删除
            this.zr.delShape(oldMap[key].id);
          }
        }

        for (key in newMap) {
          if (oldMap[key]) {
            // 新旧都有 动画过渡
            this.zr.delShape(oldMap[key].id);

            this._animateMod(oldMap[key], newMap[key], duration, easing, 0, isUpdate);
          } else {
            // 新有旧没有  添加并动画过渡
            //this._animateAdd(newMap[key], duration, easing);
            delay = (this.type == ecConfig.CHART_TYPE_LINE || this.type == ecConfig.CHART_TYPE_RADAR) && key.indexOf('icon') !== 0 ? duration / 2 : 0;

            this._animateMod(false, newMap[key], duration, easing, delay, isUpdate);
          }
        }

        this.zr.refresh();
        this.animationEffect();
      } else {
        this.motionlessOnce = false; // clear old

        this.zr.delShape(lastShapeList); // 直接添加

        for (var i = 0, l = shapeList.length; i < l; i++) {
          this.zr.addShape(shapeList[i]);
        }
      }
    },
    _getAnimationKey: function (shape) {
      if (this.type != ecConfig.CHART_TYPE_MAP && this.type != ecConfig.CHART_TYPE_TREEMAP && this.type != ecConfig.CHART_TYPE_VENN && this.type != ecConfig.CHART_TYPE_TREE) {
        return ecData.get(shape, 'seriesIndex') + '_' + ecData.get(shape, 'dataIndex') + (shape._mark ? shape._mark : '') + (this.type === ecConfig.CHART_TYPE_RADAR ? ecData.get(shape, 'special') : '');
      } else {
        return ecData.get(shape, 'seriesIndex') + '_' + ecData.get(shape, 'dataIndex') + (shape._mark ? shape._mark : 'undefined');
      }
    },

    /**
     * 动画过渡 
     */
    _animateMod: function (oldShape, newShape, duration, easing, delay, isUpdate) {
      switch (newShape.type) {
        case 'polyline':
        case 'half-smooth-polygon':
          ecAnimation.pointList(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'rectangle':
          ecAnimation.rectangle(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'image':
        case 'icon':
          ecAnimation.icon(this.zr, oldShape, newShape, duration, easing, delay);
          break;

        case 'candle':
          if (!isUpdate) {
            ecAnimation.candle(this.zr, oldShape, newShape, duration, easing);
          } else {
            this.zr.addShape(newShape);
          }

          break;

        case 'ring':
        case 'sector':
        case 'circle':
          if (!isUpdate) {
            // 进入动画，加旋转
            ecAnimation.ring(this.zr, oldShape, newShape, duration + (ecData.get(newShape, 'dataIndex') || 0) % 20 * 100, easing);
          } else if (newShape.type === 'sector') {
            ecAnimation.sector(this.zr, oldShape, newShape, duration, easing);
          } else {
            this.zr.addShape(newShape);
          }

          break;

        case 'text':
          ecAnimation.text(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'polygon':
          if (!isUpdate) {
            ecAnimation.polygon(this.zr, oldShape, newShape, duration, easing);
          } else {
            ecAnimation.pointList(this.zr, oldShape, newShape, duration, easing);
          }

          break;

        case 'ribbon':
          ecAnimation.ribbon(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'gauge-pointer':
          ecAnimation.gaugePointer(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'mark-line':
          ecAnimation.markline(this.zr, oldShape, newShape, duration, easing);
          break;

        case 'bezier-curve':
        case 'line':
          ecAnimation.line(this.zr, oldShape, newShape, duration, easing);
          break;

        default:
          this.zr.addShape(newShape);
          break;
      }
    },

    /**
     * 标注动画
     * @param {number} duration 时长
     * @param {string=} easing 缓动效果
     * @param {Array=} shapeList 指定特效对象，不指定默认使用this.shapeList
     */
    animationMark: function (duration, easing, shapeList) {
      var shapeList = shapeList || this.shapeList;

      for (var i = 0, l = shapeList.length; i < l; i++) {
        if (!shapeList[i]._mark) {
          continue;
        }

        this._animateMod(false, shapeList[i], duration, easing, 0, true);
      }

      this.animationEffect(shapeList);
    },

    /**
     * 特效动画
     * @param {Array=} shapeList 指定特效对象，不知道默认使用this.shapeList
     */
    animationEffect: function (shapeList) {
      !shapeList && this.clearEffectShape();
      shapeList = shapeList || this.shapeList;

      if (shapeList == null) {
        return;
      }

      var zlevel = ecConfig.EFFECT_ZLEVEL;

      if (this.canvasSupported) {
        this.zr.modLayer(zlevel, {
          motionBlur: true,
          lastFrameAlpha: this.option.effectBlendAlpha || ecConfig.effectBlendAlpha
        });
      }

      var shape;

      for (var i = 0, l = shapeList.length; i < l; i++) {
        shape = shapeList[i];

        if (!(shape._mark && shape.effect && shape.effect.show && ecEffect[shape._mark])) {
          continue;
        }

        ecEffect[shape._mark](this.zr, this.effectList, shape, zlevel);

        this.effectList[this.effectList.length - 1]._mark = shape._mark;
      }
    },
    clearEffectShape: function (clearMotionBlur) {
      var effectList = this.effectList;

      if (this.zr && effectList && effectList.length > 0) {
        clearMotionBlur && this.zr.modLayer(ecConfig.EFFECT_ZLEVEL, {
          motionBlur: false
        });
        this.zr.delShape(effectList); // 手动清除不会被 zr 自动清除的动画控制器

        for (var i = 0; i < effectList.length; i++) {
          if (effectList[i].effectAnimator) {
            effectList[i].effectAnimator.stop();
          }
        }
      }

      this.effectList = [];
    },

    /**
     * 动态标线标注添加
     * @param {number} seriesIndex 系列索引
     * @param {Object} markData 标线标注对象，支持多个
     * @param {string} markType 标线标注类型
     */
    addMark: function (seriesIndex, markData, markType) {
      var serie = this.series[seriesIndex];

      if (this.selectedMap[serie.name]) {
        var duration = this.query(this.option, 'animationDurationUpdate');
        var easing = this.query(this.option, 'animationEasing'); // 备份，复用_buildMarkX

        var oriMarkData = serie[markType].data;
        var lastLength = this.shapeList.length;
        serie[markType].data = markData.data;
        this['_build' + markType.replace('m', 'M')](seriesIndex);

        if (this.option.animation && !this.option.renderAsImage) {
          // animationMark就会addShape
          this.animationMark(duration, easing, this.shapeList.slice(lastLength));
        } else {
          for (var i = lastLength, l = this.shapeList.length; i < l; i++) {
            this.zr.addShape(this.shapeList[i]);
          }

          this.zr.refreshNextFrame();
        } // 还原，复用_buildMarkX


        serie[markType].data = oriMarkData;
      }
    },

    /**
     * 动态标线标注删除
     * @param {number} seriesIndex 系列索引
     * @param {string} markName 标线标注名称
     * @param {string} markType 标线标注类型
     */
    delMark: function (seriesIndex, markName, markType) {
      markType = markType.replace('mark', '').replace('large', '').toLowerCase();
      var serie = this.series[seriesIndex];

      if (this.selectedMap[serie.name]) {
        var needRefresh = false;
        var shapeList = [this.shapeList, this.effectList];
        var len = 2;

        while (len--) {
          for (var i = 0, l = shapeList[len].length; i < l; i++) {
            if (shapeList[len][i]._mark == markType && ecData.get(shapeList[len][i], 'seriesIndex') == seriesIndex && ecData.get(shapeList[len][i], 'name') == markName) {
              this.zr.delShape(shapeList[len][i].id);
              shapeList[len].splice(i, 1);
              needRefresh = true;
              break;
            }
          }
        }

        needRefresh && this.zr.refreshNextFrame();
      }
    }
  };
  zrUtil.inherits(Base, ComponentBase);
  return Base;
}(require);